본문 바로가기
algorithm/codility

[Codility] CountSemiPrime 풀이 정리 (Java)

by 무대포 개발자 2022. 6. 9.
728x90
반응형

source 는 Github 에 있습니다.

문제

풀이

첫번째 풀이

  • 전체적인 concept 은 P 의 최소 값을 구한 후, P~N 까지 SemiPrime 을 구해서 cache 에 저장합니다.
    • cache[P+2] 라는 것은 P+2 까지 위치에서 SemiPrime 이 몇 개인지를 나타내는 것입니다.
    • 예를 들면, P가 4 이고 N 이 10이면, cache[4] = 1 이고, cache[10] = 4 입니다.
  • P, Q 를 순회하면서 cache[Q[i]] - cache[P[i]] 를 구합니다.
    • 이 수식이 의미하는 바는 Q[i] 에서의 SemiPrime 의 개수에서 P[i] SemiPrime 수를 빼서 구하겠다는 것입니다.
    • 주의할 것은 cache[Q[i]] - cache[P[i]] 를 구할 때, P[i] 가 SemiPrime 이면 +1 을 해줘야하는 것입니다.
  • SemiPrime, Prime 을 구할 때, root 를 적용한 값까지만 구해도 됩니다.
  • 시간복잡도 O(nlogn), 공간복잡도 O(n)

source

    public int[] solution(int N, int[] P, int[] Q) {
        int[] cache = new int[N + 1];
        int[] arrayP = new int[P.length];
        Arrays.fill(arrayP, Integer.MAX_VALUE);

        int[] result = new int[P.length];

        for (int i = 0 ; i < P.length ; i++) {
            arrayP[i] = P[i];
        }

        Arrays.sort(arrayP);


        int min = arrayP[0];
        cache[min] = isSemiPrime(min) ? 1 : 0;
        for (int i = min + 1 ; i <= N ; i++) {
            cache[i] = cache[i-1] + (isSemiPrime(i) ? 1 : 0);
        }

        // P, Q 를 순회
        for (int i = 0 ; i < P.length ; i++) {
            result[i] = cache[Q[i]] - cache[P[i]];
            result[i] += isSemiPrime(P[i]) ? 1 : 0;
        }
        return result;
    }

    /**
     * X 라는 양수가 있다고 가정
     * X = A * B 로 이루어짐.
     * 이 때, A 또는 B 중 1개는 루트 X 보다 크거나 작아야 함.
     * ex) X = 36 이라 한다면, 1*36, 2 * 18, 3 * 12, ... , 18 * 2, 36 * 1 이런식으로 진행이 됨.
     *     위와 같이 2개의 숫자중 1개는 반드시 루트 X 보다 크거나 작아야 함.
     *     그렇다면 루트 X 보다 크거나 작은 숫자는 소수여야 prime 겠지?
     *
     * 시간복잡도 O(루트n)
     * @param num
     * @return
     */
    private boolean isPrime(int num) {
        if (num < 2) {
            return true;
        }

        for (int i = 2 ; i <= Math.sqrt(num) ; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }

    private boolean isSemiPrime(int num) {
        boolean isExistSemiPrime = false;

        if (num < 2) {
            return false;
        }

        for (int i = 2 ; i <= Math.sqrt(num) ; i++) {
            if (num % i == 0) {
                if ( !isPrime(i) || !isPrime(num / i)) {
                    return false;
                } else if (isExistSemiPrime) {
                    return false;
                } else {
                    isExistSemiPrime = true;
                }
            }
        }
        return isExistSemiPrime;
    }

'algorithm > codility' 카테고리의 다른 글

[Codility] CountNonDivisible 풀이 정리 (Java)  (0) 2022.06.09

댓글