[아이디어]

그냥 구현 하는 식으로 풀었습니다.

 

 

[요약]

카드를 조합해 나올 수 있는 소수 찾기

 

 

[방법]

문자열에서 각 자리를 분리해

0~9까지 정수를 추출 합니다.

 

카드 조합 중 나올 수 있는 가장 큰 수를 찾습니다.

 

1부터 방금 구한 가장 큰 수까지

소수를 판별합니다.

 

카드를 조합해

조합한 수가 소수인지 아닌지 판별해줍니다.

 

 

[설명]

dfs(모든 카드의 장수, 재귀 단계, 카드 조합을 통해 구한 수)

백트래킹을 사용해 모든 카드 조합을 찾음

 

vector에서 중복 값을 제거

//-----------------------------------------------------
// 중복 제거 처리
    
// 중복을 제거하기 위한 정렬을 한다.
sort(ans.begin(), ans.end());
// unique()는 중복된 값을 vector의 가장 뒤로 보내고
// 이러한 값을 보낸 시작 위치를 반환한다.
// erase()를 사용해 중복값이 존재하는 위치부터 끝까지 지워준다.
ans.erase(unique(ans.begin(), ans.end()),ans.end());
//-----------------------------------------------------

중복을 제거하기 위해 unique()를 사용합니다.

다만,

정렬되지 않은 vector에 대해 unique를 적용한다면 아무런 변화가 없습니다.

그렇기에

unique()를 적용하기 전에 vector를 먼저 정렬해주고

unique()를 적용하면 중복값이 제거되.....

.....

.....

지 않습니다.

그 이유는 중복값을 vector의 끝 부분에 보냈을 뿐

vector 끝 부분에 존재하기 때문입니다.

또한 unique()는 중복값을 보낸 시작위치를 가르킵니다.

 

그래서,

erase()함수를 통해 unique()가 가르킨 위치부터

마지막까지 지워주면

깔끔하게 중복값은 제거됩니다.

 

 

[코드]

#include <cstring>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

#define N_MAX 10000000
#define FOR(i,s,e) for(int i=s; i<e; ++i)

vector<int> v;
bool arr[N_MAX];
int num;
vector<int> ans;
vector<int> used;

void dfs(int max_lv, int lv, int n) {
    if (max_lv == lv) {
        if (arr[n] == true)  ans.push_back(n);
        return;
    }
    FOR(i, 0, v.size()) {
        if (used[i] == 1) continue;
        used[i] = 1;
        n = (n * 10) + v[i];
        dfs(max_lv, lv + 1, n);
        n = (n / 10);
        used[i] = 0;
    }
}

int solution(string numbers) {
    int answer = 0;

    //-----------------------------------------------------
    //문자열에서 각 숫자 카드를 '한장 씩' 추출
    FOR(i, 0, numbers.length()) {
        v.push_back(int(numbers[i] - '0'));
    }
    //-----------------------------------------------------


    //-----------------------------------------------------
    //가장 큰 수를 확인하기 위해 내림차순으로 정렬
    sort(v.begin(), v.end(), greater<int>());

    // num변수에 가장 큰 수 저장
    FOR(i, 0, v.size()) {
        num = (num * 10) + v[i];
    }
    //-----------------------------------------------------

    
    //-----------------------------------------------------
    // 소수확인 후 판별하기 위한 arr배열 초기화
    // 소수라면 true, 아니라면 false
    memset(arr, true, sizeof(arr));
    
    // 0과 1은 소수가 아니다.
    arr[0] = false;
    arr[1] = false;

    // 가장 큰 수 9999999이므로 배열의 크기는 10000000
    // 카드 조합 중 나올 수 있는 가장 큰 수(num)까지 소수 판별을 한다.
    FOR(i, 1, 10000000) {
        if (arr[i] == false) continue;
        int s = i;
        for (int j = i * 2; j <= num; j += i) {
            arr[j] = false;
        }
    }
    //-----------------------------------------------------

    //-----------------------------------------------------
    // 카드를 조합해 나올 수 있는 모든 수를 구한다.
    FOR(i, 1, v.size() + 1) {
        used = vector<int>(v.size(), 0);
        dfs(i, 0, 0);
    }
    //-----------------------------------------------------

    
    //-----------------------------------------------------
    // 중복 제거 처리
    
    // 중복을 제거하기 위한 정렬을 한다.
    sort(ans.begin(), ans.end());
    // unique()는 중복된 값을 vector의 가장 뒤로 보내고
    // 이러한 값을 보낸 시작 위치를 반환한다.
    // erase()를 사용해 중복값이 존재하는 위치부터 끝까지 지워준다.
    ans.erase(unique(ans.begin(), ans.end()),ans.end());
    //-----------------------------------------------------

    answer = ans.size();
    return answer;
}

 

[문제 출처]

https://school.programmers.co.kr/learn/courses/30/lessons/42839

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

반응형

'Problem Solving > 프로그래머스' 카테고리의 다른 글

[프로그래머스] 카펫 (C++)  (0) 2024.01.26

+ Recent posts