프로그래머스 - 소수찾기 [java]

Stella·2021년 12월 5일
4

Coding Test

목록 보기
11/48

문제링크: https://programmers.co.kr/learn/courses/30/lessons/12921

소수 찾기

문제 설명
1부터 입력받은 숫자 n 사이에 있는 소수의 개수를 반환하는 함수, solution을 만들어 보세요.
소수는 1과 자기 자신으로만 나누어지는 수를 의미합니다.
(1은 소수가 아닙니다.)

제한 조건
n은 2이상 1000000이하의 자연수입니다.

입출력 예 #1
1부터 10 사이의 소수는 [2,3,5,7] 4개가 존재하므로 4를 반환
입출력 예 #2
1부터 5 사이의 소수는 [2,3,5] 3개가 존재하므로 3를 반환

Solution 1

public int solution(int n) {
     int answer = 0;
     for(int i=2; i<=n; i++){
         boolean flag = true;
         for(int j=2; j<=Math.sqrt(i); j++) {
        	 if(i%j == 0)  { //나누어떨어지면 소수X
        	   flag = false; //falg를 false로 바꿔서 소수가 아니라고 체크
                   break; //break를 안해주면 효율성 테스트 통과 못함
        	  } 
           }
      if(flag==true) //소수인 숫자는 flag가 변하지 않고 true 
         answer++; 
    }
   return answer;
}

배열에 있는 숫자가 j로 나누어떨어지면 소수가 아니기 때문에 flag를 false로 바꾸어준다. flag가 그대로 true라면 소수라는 뜻이므로 숫자를 카운트해줘서 소수의 개수를 찾을 수 있다.

Solution 2 - 에라토스테네스의 체 사용

public int solution(int n) { 
      int answer = 0; 
      boolean[] prime = new boolean [n+1]; 
      for(int i=2; i<=n ; i++) 
      prime[i]=true; //2~n번째수를 true로 초기화 
      
      //제곱근 구하기 
      int root=(int)Math.sqrt(n); 
      for(int i=2; i<=root; i++){ //2~루트n까지 검사 
      if(prime[i]==true){ //i번째의 수가 소수일 때 
      	 for(int j=i; i*j<=n; j++) //그 배수들을 다 false로 초기화(배수는 소수가 아니기 때문) 
             prime[i*j]=false; 
         } 
      } 
      
      for(int i =2; i<=n; i++) { 
      if(prime[i]==true)
         answer++; 
      } 
      return answer; 
  }

효율성을 통과하기 어려웠어서 다른 분들은 어떻게 코드를 짰는지 찾아보았다. 에라토스테네스의 체를 사용해서 작성된 코드.

1. 2부터 소수를 구하고자 하는 구간의 모든 수를 나열한다. 그림에서 회색 사각형으로 두른 수들이 여기에 해당한다.
2. 2는 소수이므로 오른쪽에 2를 쓴다. (빨간색)
3. 자기 자신을 제외한 2의 배수를 모두 지운다.
4. 남아있는 수 가운데 3은 소수이므로 오른쪽에 3을 쓴다. (초록색)
5. 자기 자신을 제외한 3의 배수를 모두 지운다.
6. 남아있는 수 가운데 5는 소수이므로 오른쪽에 5를 쓴다. (파란색)
7. 자기 자신을 제외한 5의 배수를 모두 지운다.
8. 남아있는 수 가운데 7은 소수이므로 오른쪽에 7을 쓴다. (노란색)
9. 자기 자신을 제외한 7의 배수를 모두 지운다.
10. 위의 과정을 반복하면 구하는 구간의 모든 소수가 남는다.

Ref:
https://wooaoe.tistory.com/50

profile
Hello!

0개의 댓글