• Feed
  • Explore
  • Ranking
/
/
    맞았습니다!!

    PGS : 프로그래머스 소수 찾기 (JAVA)

    프로그래머스 소수 찾기 풀이 기록 💡
    알고리즘순열
    t
    t1s
    2025.04.29
    ·
    6 min read

    문제

    문제
    한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다.
    각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이 조각으로 만들 수 있는 소수가 몇 개인지 return 하도록 solution 함수를 완성해주세요.

    입력
    String으로 조합할 수 있는 0~9 사이의 숫자들이 1~7개까지
    e.g., "17", "011" 등

    출력
    만들 수 있는 숫자 중 소수인 숫자의 개수
    중복 안 되고, 011 == 11 동일하게 취급

    풀이

    일단 같은 숫자를 여러 번 카운트하면 안 되므로 HashSet을 사용하여 중복을 제거했다.
    소수임을 판별하는 방법은 에라테스토네스의 체를 사용하면 효율성이 더 높을 것 같아 쓰고 싶었고... 가능한 최대의 수 9가 7개인 수 + 1 = 10000000를 인덱스로 박고 에라테스토네스 체를 사용해도 될 것 같지만 이왕 효율성을 신경 쓰는 김에 만들 수 있는 수 중 max 수를 찾아 max+1를 배열 인덱스로 하고 구현하고 싶었다.

    구현 코드는 아래와 같다.

    import java.util.*;
    
    class Solution {
        static HashSet<Integer> set;
        static int max;
        
        public int solution(String numbers) {
            int answer = 0;
            
            set = new HashSet<>();
            max = 0;
            
            // 이미 체크한 수인지를 확인하기 위해 isVisited 배열 사용
            boolean[] visited = new boolean[numbers.length()];
            Arrays.fill(visited, false);
            
            permutation(numbers, "", visited); // 순열 함수를 사용하여 set에 가능한 수를 모두 추가
            
            // 에라토스테네스의 체를 사용하여 소수 체크
            Boolean[] isPrime = new Boolean[max+1];
            Arrays.fill(isPrime, true); // 초기화
            
            for(int i=2; i<Math.sqrt(isPrime.length)+1; i++) {
                if(isPrime[i] == false) { // 이미 false인 경우 continue
                    continue;
                }
                
                for(int j=2; j*i<isPrime.length; j++) {
                    isPrime[j*i] = false; // i*j는 전부 false 처리, 이후 true로 남은 것들만이 소수에 해당
                }
            }
            
            for(int i : set) {
                if(i < 2) {
                    continue;
                }
                
                if(isPrime[i] == true) {
                    answer++;
                }
            }
            
            
            return answer;
        }
        
        static void permutation(String numbers, String current, boolean[] visited) {
            if(!current.isEmpty()) {
                set.add(Integer.parseInt(current));
                max = Math.max(max, Integer.parseInt(current));
            }
            
            for(int i=0; i<numbers.length(); i++) {
                if(!visited[i]) {
                    visited[i] = true;
                    permutation(numbers, current + numbers.charAt(i), visited);
                    visited[i] =false;
                }
            }
        }
    }
    1. 순열(permutation)
      visited 배열은 방문한 숫자인지를 확인하는 배열이다.
      numbers.length()까지 for문을 돈다.
      만약 visited[i] = false이면,
      visited[i]를 true로 변경하고
      현재 current에 numbers[i]를 추가하고 재귀
      visited[i]를 다시 false로 변경한다.
      이러면 permutation에 들어왔을 때 current가 비지 않았으므로 set에 저장하게 된다.
      예시를 들자면 123의 경우
      처음에 들어왔을 때 visited[f, f, f] for문 i는 0부터 시작하므로
      current = 1, 재귀함수 들어가서 hashSet에 1이 저장된다.
      이후 밑으로 for문 들어와서 현 current = 1, visited[t, f, f]이므로
      12, 13가 set에 저장 -> 여기서 또 재귀 들어가니까 123, 132을 set에 저장
      이 과정에서 Math.max를 통해 max 값을 미리 구해둔다.

    2. 소수 판별(에라테스토네스의 체)
      max+1을 isPrime[] 배열의 인덱스 값으로 넣는다.
      isPrime 배열을 먼저 true로 전부 초기화 시킨다.
      Math.sqrt(length) +1까지만 for문을 돌리고
      이중 for문으로 j=2부터, j*i가 length 미만일 때만
      i는 제외하고 isPrime[j*i] = false;로 저장해둔다.

    3. hashSet을 돌며 isPrime[hashSet의 값 중 하나] = true인지 판단, result++;

    // 1. 그냥 for문 돌리기
    for(int x : hashSet) { ... }
    // 2. iterator
    Iterator<Integer> iter = hashSet.iterator();
    while(iter.hasNext()) {
    	...
    }
    

    문제를 풀며

    어려웠던 점은 어떻게 가능한 모든 조합의 숫자를 만들지 생각하는 거였다. 순열을 떠올려서 풀기는 했지만...

    그리고 오랜만에 iterator로 변경해서 쓰려고 하는데 기억 나질 않아서.. 포기하고 for문 썼다. 처음엔 set.ketSet();을 for문으로 돌리다 에러 나서 ㅋㅋㅋ 삽질 좀 하다 결국 풀어냈다🥹 이런 삽질은 사실 공식 문서 찾아보면 해결할 수 있다고 해도 바로바로 딱딱 적는 것과 일일히 찾아보는 것은... 시간 차이가 나니까 최대한 손에 익히게 하려는 편이다. 시간을 쪼끔 더 썼더라두! 이렇게 삽질 한 번 하면 오래 기억하니까... 가뜩이나 안 풀리는 문제도 많은데 문법 때문에 일일히 발 걸려 넘어지면 안 된다...







    - 컬렉션 아티클