완전 탐색
가능한 방법을 전부 만들어 보는 알고리즘으로 컴퓨터의 빠른 계산 속도를 이용하는 방법이다.
- Brute Force : for문과 if문을 이용하여 처음부터 끝까지 탐색하는 방법
- 비트 마스크
- 순열, 조합
- 백트래킹
- BFS
문제
문제 설명
한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다.
각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이 조각으로 만들 수 있는 소수가 몇 개인지 return 하도록 solution 함수를 완성해주세요.
** 제한사항 **
- numbers는 길이 1 이상 7 이하인 문자열입니다.
- numbers는 0~9까지 숫자만으로 이루어져 있습니다.
- 013은 0, 1, 3 숫자가 적힌 종이 조각이 흩어져있다는 의미입니다.
** 입출력 예 **
numbers | return |
---|---|
17 | 3 |
011 | 2 |
** 입출력 예 설명 **
- 예제 #1
- [1, 7]으로는 소수 [7, 17, 71]를 만들 수 있습니다.
- 예제 #2
- [0, 1, 1]으로는 소수 [11, 101]를 만들 수 있습니다.
- 11과 011은 같은 숫자로 취급합니다.
문제 풀이
주어진 숫자로 만들 수 있는 모든 순열을 구하는게 어려웠다. 소수 찾는 건 금방 생각해 냈는데 이부분을 시간 내에 해결하지 못해서 결국 구글링해보았다…
여러 사람의 블로그를 보았는데 다들 코드가 엄청 길다.
static boolean[] visited;
static int ans;
static char[] chs;
static char[] select; // 순열
static HashSet<Integer> set; // 소수 저장 (중복 제거)
public static int solution(String numbers){
chs = numbers.toCharArray();
int size = numbers.length();
visited = new boolean[size];
ans = 0;
set = new HashSet<>();
for(int i=1; i<=size; i++){
select = new char[i];
perm(0, i, size);
}
return set.size();
}
public static void perm(int start, int r, int n){
if(start == r){
// 숫자로 변환
String str = "";
for(int i=0; i<select.length; i++)
str += select[i];
int num = Integer.parseInt(str);
// 예외 처리
if(num == 1 || num == 0)
return;
// 소수 인지 검사
boolean flag = false;
for(int i=2; i<=Math.sqrt(num); i++){
if(num % i == 0)
flag = true;
}
if(!flag)
set.add(num);
return;
}
for(int i=0; i<n; i++){
if(!visited[i]){
visited[i] = true;
select[start] = chs[i];
perm(start+1, r, n);
visited[i] = false;
}
}
}
- 모든 순열을 확인
- start를 0부터 증가시키면서 select 배열에 순차적으로 삽입한다.
- 재귀적으로 perm(start+1, r, n)을 호출한다.
- 구한 문자를 숫자로 바꾸어 소수인지 판단 ==> 해당 숫자의 루트값까지 나누어 확인
참고
코드 출처 (정리 굿) 코드 참고 (정말 똑똑하신 분 같음) 소수찾기 순열
회고
숫자 조합을 어떻게 배열에 저장할지 생각해보느라 오래걸렸다. 예전부터 순열 조합이 어려웠는데 극복이 안된다. 그래도 이번 문제로 다시 정리할 수 있어서 좋았다. 다시봐야지