[プログラマレベル1]小数点以下の問題解決



に質問


1から入力した数字nまでの小数を返す関数を作成します.
小数は1とそれ自体の数です.
(1は小数ではありません.)

せいげんじょうけん

  • nは2以上100000以下の自然数です.
  • 🖨️ I/O例



    エラトステネスのふるい


    1. 2から素数を求めたい区間の全数をリストする.図中の灰色の矩形で囲まれた数はこれに相当する.
    2.2は小数で、右に2と書きます.(赤)
    3.自分以外の2の倍数を取り除く.
    4.残りの数は3が小数なので、右に3と書きます.(緑)
    5.自分を除いて、3の倍数をすべて削除します.
    6.残りの数のうち5は小数なので、右に5と書きます.(青)
    [原句]自分以外の5倍を消す.
    8.残りの数のうち7は小数で、右に7と書きます.(黄色)
    9.自分以外の7の倍数を抜く.
    10.以上の過程を繰り返し、求めた区間のすべての少数の残り.
    図に示すように、11^2>120は、11未満の倍数を削除するだけでよい.すなわち,120以下の数では,2,3,5,7の倍数を除いて残りは少数である.

    進行方法

    1. 1차원 배열 생성 (n+1 크기)
    2. 2부터 배수들을 모두 체크 (단, 자신은 제외하고 4,6,8,10..... <= n)
    3. 다음으로 3의 배수들을 모두 체크
    4. 4는 아선 2의 배수로써 체크가 되어 소수가 아니기 때문에 PASS
    5. ,,,

    💡 に答える

    class Solution {
    
        public int solution(int n) {
            int answer = 0;
            // 에라토스테네스의 체로 거르기 위한 배열
            boolean[] flag = new boolean[n + 1];
    
            // 2부터 n까지의 수들을 지나며
            int i = 1;
            while(1 < ++i && i < n) {
    
                // 이미 걸러진 수(소수의 배수)는 PASS
                if(flag[i])
                    continue;
                
                // 소수의 배수를 체크
                for(int j = i + i; j <= n; j += i)
                    flag[j] = true;
    
            }
    
            // 걸러지지 않은 수의 개수 구하기
            for(int idx = 2; idx <= n; idx++) {
                 if(!flag[idx])
                     answer++;
            }
    
            return answer;
        }
    
    }

    ✏️ comment


    最初は効率テストで淘汰されて慌てていましたが、
    少数を見つけたときは、에라토스테네스의 체を使いましょう!