k진수에서 소수 개수 구하기(Java)

bearMin·2024년 1월 30일

🎯문제

양의 정수 n이 주어집니다. 이 숫자를 k진수로 바꿨을 때, 변환된 수 안에 아래 조건에 맞는 소수(Prime number)가 몇 개인지 알아보려 합니다.

0P0처럼 소수 양쪽에 0이 있는 경우
P0처럼 소수 오른쪽에만 0이 있고 왼쪽에는 아무것도 없는 경우
0P처럼 소수 왼쪽에만 0이 있고 오른쪽에는 아무것도 없는 경우
P처럼 소수 양쪽에 아무것도 없는 경우
단, P는 각 자릿수에 0을 포함하지 않는 소수입니다.
예를 들어, 101은 P가 될 수 없습니다.
예를 들어, 437674을 3진수로 바꾸면 211020101011입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 왼쪽부터 순서대로 211, 2, 11이 있으며, 총 3개입니다. (211, 2, 11을 k진법으로 보았을 때가 아닌, 10진법으로 보았을 때 소수여야 한다는 점에 주의합니다.) 211은 P0 형태에서 찾을 수 있으며, 2는 0P0에서, 11은 0P에서 찾을 수 있습니다.

정수 n과 k가 매개변수로 주어집니다. n을 k진수로 바꿨을 때, 변환된 수 안에서 찾을 수 있는 위 조건에 맞는 소수의 개수를 return 하도록 solution 함수를 완성해 주세요.

제한사항
1 ≤ n ≤ 1,000,000
3 ≤ k ≤ 10

입출력 예

nkresult
43767433
110011102

✏️풀이

코드

class Solution {
    public int solution(int n, int k) {
        int answer = 0;
		// n을 k진수로 변환
        String formation = Long.toString(n, k);
        // 0을 기준으로 나눠줌
		String[] num = formation.split("0");
        
        for(String s : num) {
			// 값이 없거나 1만 있을 경우 continue
            if(s.equals("") || s.equals("1")) continue;
            
			// 소수 판별을 위한 변수
            boolean isPrime = true;
			// 문자열을 숫자로 변환
            long temp = Long.parseLong(s);
            
			// 소수 판별
            for(int i = 2; i <= Math.sqrt(temp); i++) {
				// 만일 나누어 떨어지는 값이 있다면 소수가 될 수 없음
                if(temp % i == 0) {
                    isPrime = false;
                    break;
                }
            }
            
			// 소수라면 1을 아니라면 0을 더해줌
            answer += isPrime ? 1 : 0;
        }
        
        return answer;
    }
}

설명

우선 주어진 정수 n을 k진수로 바꿔줘야했다. 어떻게 바꿀지 고민을 하다가 바꿔주는 함수를 사용하기로 했다.
toString(n, k) 함수는 정수 n을 k진수로 바꿔서 문자열로 반환을 해주는 함수이다.

이후 문자열로 반환을 받고 0을 기준으로 값을 나눠준다. 이때 0을 기준으로 나눠주는 이유는 P는 각 자릿수에 0을 포함하지 않는 소수이기 때문이다.

나눠준 값을 하나씩 탐색한다. 이때 0을 기준으로 나누었기 때문에 00과 같이 0이 연달아 있는 경우 ""와 같은 값이 배열에 들어갈 수 있다. 또한 "1" 역시 들어갈 수 있는데 이 둘은 소수가 되지 않기 때문에 조건문을 통해 다음으로 바로 넘어갈 수 있도록 한다.

소수를 판별할 때 Math.sqrt(temp) 함수를 사용해야한다.
예를 들어 16이 소수인지 판별을 할 경우를 살펴보면,
16의 약수에는 [1, 2, 4, 8, 16]이 있다.
이때 16의 제곱근인 4를 넘어가는 순간 그보다 작은 값에서 먼저 나누어 떨어진다. 즉, 나누어 떨어지는 수를 판별하기 위한 가장 큰 값이 제곱근인 것이다.

이 부분은 시간의 효율에서 많은 도움이 된다.
무작정 절반으로 나누었다가 시간초과가 떴다..

이렇게 반복문을 돌려 나누어 떨어지는 값이 없다면 소수가 되고, 이때 answer의 값을 증가시켜준다.


💡느낀 점

소수 판별과 같은 문제들을 몇번 풀어본 적 있는데 오랜만에 풀어보니 시간초과가 나지 않도록 머리를 많이 쓰게 되었다. 이번 기회를 통해 문제를 푸는 것만이 아니라 문제를 풀고 리뷰하는 시간을 가지는 것이 실력 향상에 많은 도움이 된다는 것을 알게 되었다..


링크

문제 링크

profile
소소한 공부기록

0개의 댓글