JAVA

[Java] 소수 구하는 알고리즘

배씌 2023. 5. 25. 23:21

소수(Prime Number)

: 1보다 큰 자연수 중 1과 자기 자신만을 약수로 갖는 자연수

 

방법 1) " N 이하의 자연수들로 모두 나눠본다 . "

임의의 수 N이 1과 N을 제외한 다른 수를 약수로 갖고 있다면 그 수는 소수가 아니고, 만약 약수가 없다면 소수이다.

static boolean is_prime(int n) {
    // 0과 1은 소수가 아님
    if(n < 2)
        return false;

    // 2는 소수
    if(n == 2)
        return true;

    for(int i=2; i<n; i++)
        if(n % i == 0)
            return false;

    return true;
}

위 방법의 시간 복잡도는 O(N)

 

방법 2) " √N 이하의 자연수들로 모두 나눠본다. "

임의의 자연수 N이 p X q = N 을 만족 할 때, 예를 들어 N = 16 이면

 

1 X 16

2 X 8

4 X 4

8 X 2

16 X 1

 

위와 같이 p가 증가하면 q 가 감소하고, 반대의 경우도 동일하다.

결국 N을 임의의 수로 나누게 되면 임의의 수가 √N 보다 작다면 결국 나머지는 √N 보다 클 수 밖에 없다.

 

결과적으로 p와 q 중 하나는 반드시 √N 보다 작거나 같다.

static boolean is_prime2(int n) {
	// 0과 1은 소수가 아님
    if(n < 2)
        return false;

	// 2는 소수
    if(n == 2)
        return true;

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

    return true;
}

위 방법의 시간 복잡도는 O(√N)

 

방법 3) 에라토스테네스의 체

" k=2 부터 √N 이하까지 반복하여 자연수들 중 k를 제외한 k의 배수들을 제외시킨다 "

k = 2 이면 2를 제외한 2의 배수를 모두 지우고,

k = 3 이면 3을 제외한 3의 배수를 모두 지우고,

(4는 k=2에서 이미 다 지워짐)

k = 5 이면 5를 제외한 5의 배수를 모두 지우고,

...

k=√N 까지 반복

 

 

 

 

 

 

public class Main {

	public static boolean[] prime;
	
	static void make_prime(int n) {
    	    // 0 ~ N
            prime = new boolean[n+1];

            /*
            소수가 아닌 index = true
            소수 index = false
            */

            prime[0] = prime[1] = true;

            for(int i=2; i<Math.sqrt(n); i++) {
                if(prime[i] == true)
                    continue;

                // i 의 배수들을 걸러주기 위함 (2,4,6... 등)
                for(int j=i*i; j<prime.length; j=j+i)
                    prime[j] = true;
	    }
        }
}

위 방법의 시간 복잡도는 O(Nlog(log N))

 

결론

대부분 소수 문제는 에라토스테네스의 체 쓰면 거의다 해결됨 !