1. 程式人生 > 其它 >LeetCode從讀題到自閉:204. 計數質數

LeetCode從讀題到自閉:204. 計數質數

題目:統計所有小於非負整數 n 的質數的數量

示例 1:

輸入:n = 10
輸出:4
解釋:小於 10 的質數一共有 4, 它們是 2, 3, 5, 7

示例 2:

輸入:n = 0
輸出:0

示例 3:

輸入:n = 1
輸出:0

提示:

0 <= n <= 5 * 10^6

暴力列舉:

 1 class Solution {
 2     public int countPrimes(int n) {
 3         int ans = 0;
 4         for (int i = 2; i < n; ++i) {
 5             ans += isPrime(i) ? 1 : 0;
6 } 7 return ans; 8 } 9 10 public boolean isPrime(int x) { 11 for (int i = 2; i * i <= x; ++i) { 12 if (x % i == 0) { 13 return false; 14 } 15 } 16 return true; 17 } 18 }

埃氏篩:

  • 埃拉託斯特尼篩法,簡稱埃氏篩或愛氏篩,是一種由古希臘數學家埃拉託斯特尼所提出的一種簡單檢定素數的演算法。要得到自然數n以內的全部素數,必須把不大於根號n的所有素數的倍數剔除,剩下的就是素數。
  • 就是:先去掉2的倍數,再去掉3的倍數,再去掉4的倍數,……依此類推,直到最大數小於最後一個標出的素數的平方,那麼剩下的序列中所有的數都是素數。

詳細列出演算法如下:

 1. 列出2以後的所有序列: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 2. 標出序列中的第一個素數,也就是2,序列變成: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 3. 將剩下序列中,劃掉2的倍數,序列變成: 2 3 5 7 9 11 13 15 17 19
21 23 25 4. 如果這個序列中最大數小於最後一個標出的素數的平方,那麼剩下的序列中所有的數都是素數,否則回到第二步。 5. 本例中,因為25大於2的平方,我們返回第二步: 6. 剩下的序列中第一個素數是3,將主序列中3的倍數劃掉,主序列變成: 2 3 5 7 11 13 17 19 23 25 7. 我們得到的素數有:23 8. 25仍然大於3的平方,所以我們還要返回第二步: 9. 序列中第一個素數是5,同樣將序列中5的倍數劃掉,主序列成了: 2 3 5 7 11 13 17 19 23 10. 我們得到的素數有:23511. 因為23小於5的平方,跳出迴圈. 12. 結論:225之間的素數是:2 3 5 7 11 13 17 19 23

動圖演示:(圖片來自維基百科)

程式碼:

 1 class Solution {
 2     public int countPrimes(int n) {
 3         int[] isPrime = new int[n];
 4         Arrays.fill(isPrime, 1);
 5         int ans = 0;
 6         for (int i = 2; i < n; ++i) {
 7             if (isPrime[i] == 1) {
 8                 ans += 1;
 9                 if ((long) i * i < n) {
10                     for (int j = i * i; j < n; j += i) {
11                         isPrime[j] = 0;
12                     }
13                 }
14             }
15         }
16         return ans;
17     }
18 }