Programmers
[프로그래머스 Level.2] 소수 찾기 (완전탐색) (Java)
Devtraces
2022. 12. 30. 14:20
문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/42839
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
코딩테스트 연습 > 완전탐색 > 소수 찾기
문제 설명
한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다.
각 종이 조각에 적힌 숫자가 적힌 문자열 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은 같은 숫자로 취급합니다.
나의 코드
import java.util.*;
class Solution {
boolean[] visited;
Set<Integer> set;
public int solution(String numbers) {
int answer = 0;
boolean flag = true;
visited = new boolean[numbers.length()];
set = new HashSet<>();
char[] numArr = numbers.toCharArray();
StringBuilder sb = new StringBuilder();
dfs(numArr, sb);
for(Integer s : set) {
if(s <= 1) continue;
flag = true;
for(int i=2; i<=Math.sqrt(s); i++) {
if(s%i == 0) {
flag = false;
break;
}
}
if(flag) answer++;
}
return answer;
}
public void dfs(char[] numArr, StringBuilder sb) {
for(int i=0; i<numArr.length; i++) {
if(!visited[i]) {
visited[i] = true;
sb.append(numArr[i]);
set.add(Integer.parseInt(String.valueOf(sb)));
dfs(numArr, sb);
visited[i] = false;
sb.setLength(sb.length()-1);
}
}
}
}
풀이
- numbers를 완전탐색을 이용하여 모든 가능한 숫자를 만들어 중복을 제거하기 위해 Set에 넣고 이 숫자들 중에서 소수가 몇개인지 카운팅 해서 풀었다.
- 우선 Integer를 선언 타입으로 하는 Set을 만들고 numbers 문자열을 완전탐색 할 때 이용하기 위해 numbers 크기의 boolean형 배열 visited를 생성한다.
- numbers를 toCharAray()를 이용하여 char 타입 배열 numArr에 담는다.
- 완전탐색을 하면서 모든 문자열을 만들기 위해 StringBuilder를 만들고 완전탐색 dfs(깊이 우선 탐색)을 진행한다.
- numArr을 for문을 돌면서 인덱스를 방문하지 않았다면 StringBuilder에 append 하고 해당 StringBuilder를 Set에 담아주고 해당 인덱스를 방문했으므로 visited[i]를 true로 바꿔준다.
- 그리고 현재 StringBuilder를 가지고 다시 dfs() 메소드를 recursive 호출하고 다음 탐색을 위해 visited[i]를 false로 바꾸고 이번에 StringBuilder에 append() 해주었던 문자를 sb.setLength(sb.length()-1)을 이용하여 제거한다.
- 이렇게 모든 가능한 숫자들을 구해서 Set에 담아주면 중복을 제거하고 모든 숫자들이 담겨있다.
- 이제 이 Set에 담긴 숫자들을 for each문을 돌면서 소수가 몇 개인지 카운팅하면 된다.
- 소수(prime number)는 약수를 1과 자기 자신만 가지는 수이므로 우선 숫자 s가 1이하이면 소수가 아니니 넘어가고 2 이상이라면 flag를 두고 true로 시작해서 2 ~ 루트 s 까지 s를 나눈 나머지가 0이 되는 수가 있다면 flag를 false로 바꾼다. 2 ~ 루트 s 까지 s를 나눈 나머지가 0이 되는 수가 없다면 flag는 그대로 true 이니 answer를 증가시킨다.
- 이렇게 하여 Set에서 소수를 카운팅하여 answer를 구해 반환한다.