소수 찾기

yejichoi·2023년 3월 22일
0

알고리즘 스터디

목록 보기
29/153
post-thumbnail

소수 찾기

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

입출력 예

nresult
104
53

입출력 예 설명

입출력 예 #1

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

입출력 예 #2

1부터 5 사이의 소수는 [2,3,5] 3개가 존재하므로 3를 반환


🥨 나의 풀이

시간 초과로 인해 효율성에서 계속 걸린다...

function solution(n) {
   let cnt = 0;
  for(let i = 2; i <= n; i++){
    var answer = 0;
    for(let j = 1 ; j <= i; j++){
      if(i % j === 0){
        answer++
        if(answer === 2 && i === j){
          cnt++
        }
      }
    }
  }
 return cnt;
}

📍 정답풀이

소수를 찾는 수많은 방법중에서 가장 많이 사용된다는 "에라토스테네스의 체"

에라토스테네스의 체

1) 2부터 소수를 구하고자 하는 구간의 모든 수를 나열한다.
2) 2는 소수이므로 오른쪽에 2를 쓴다.
3) 자기 자신을 제외한 2의 배수를 모두 지운다.
4) 남아있는 수 가운데 3은 소수이므로 오른쪽에 쓴다.
5) 자기 자신을 제외한 3의 배수를 모두 지운다.
6) 남아있는 수 가운데 5는 소수이므로 오른쪽에 쓴다.
7) 자기 자신을 제외한 5의 배수를 모두 지운다.
8) 남아있는 수 가운데 7은 소수이므로 오른쪽에 쓴다.
9) 자기 자신을 제외한 7의 배수를 모두 지운다.
10) 위의 과정을 반복하면 구하는 구간의 모든 소수가 남는다.
그림의 경우, 11^2 > 120 이므로 11보다 작은 수의 배수들만 지워도 충분하다. 즉, 120보다 작거나 같은 수 가운데 2, 3, 5, 7의 배수를 지우고 남는 수는 모두 소수이다.

function solution(n) {
    let answer = 0;
    const arr = new Array(n+1).fill(true);
      
    for(let i = 2; i <= n; ++i){
        // 이미 소수가 아닌 인덱스는 건너뛴다.
        if(arr[i] === false){
            continue;
          // 다음으로 진행하지 않고 조건이나 반복의 시작 지점에서 이어서 진행하는 것을 의미 
        }
      
        // 배수는 소수가 아니라 0으로 설정
        for(let k = i * 2; k <= n; k += i){
          //4,6,8,10
          //6,9
          //10
            arr[k] = false;
        }
    }
    // 소수의 갯수를 구한다.
    for(let i = 2; i <= n; ++i){
        if(arr[i] === true){
            answer++;
        }
    }
    return answer;
}

🌿 효율성을 위한 조언

정수론

일단 여기서는 간단히 3가지 수학 정리만 소개하겠습니다.

  • 1보다 큰 모든 자연수는 소수의 곱으로 이루어져 있다.
    이것은 가장 기본적인 정리입니다. 이 정리가 의미하는 바는 무엇일까요? 대부분의 사람들은 소수를 구하기 위해서 2부터 차례대로 증가시켜서 나누어보는 방법을 이용할 것 입니다. 그러나 이 방식은 굉장히 비효율적인입니다. 그렇지만 1보다 큰 자연수는 소수의 곱으로 이루어져 있기 때문에 소수로만 나누면 됩니다. 예를 들어서, 10이 소수인지 아닌지를 알기 위해서 10보다 작은 소수만을 이용하면 됩니다. 실제로 10보다 작은 소수는 4개입니다. 그러니깐 4개만 이용하면 됩니다. 그리고 100이 소수인지 아닌지를 알기 위해서 99개의 자연수를 모두 이용한 것 대신에 25개의 소수만 이용하면 됩니다.

  • 어떤 자연수 n이 있을 때, √n 보다 작은 모든 소수들로 나누어 떨어지지 않으면 n은 소수입니다.
    언뜻 이해하기 힘들겠지만 한 번 이해하면 쉽습니다. 증명을 생략하고 예를 들겠습니다. 먼저 101이 소수인지 아닌지 판별하기 위해서 우리는 √101을 구하면 10.xxx이 됩니다. 자 10보다 작은 소수는 뭐가 있을까요? 일단 2, 3, 5, 7이 있습니다. 그런데 딱 봐도 이 4개의 소수로만 101이 나누어 떨어지지 않습니다. 그러므로 101소수입니다. 위의 방식을 이용하면 25개의 소수를 모두 이용해야 하지만 지금은 4개만 이용해도 쉽게 계산이 됩니다.

  • 2보다 큰 모든 짝수는 어차피 합성수입니다. 어차피 2로 나누어 떨어지기 때문이죠. 이 방식은 사용하지 않았습니다. 저는 위의 2가지 방식만을 이용해서 효율성 테스트를 통과했습니다.

0개의 댓글