判斷一個數是不是質數的方法


如題:204. 計數質數

給定整數 n ,返回 所有小於非負整數 n 的質數的數量 。

示例 1:

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

輸入:n = 0
輸出:0
示例 3:

輸入:n = 1
輸出:0

提示:

0 <= n <= 5 * 106

 

方法一:

暴力枚舉:

 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 }

 

 

 

方法二:

埃氏篩:

枚舉沒有考慮到數與數的關聯性,因此難以再繼續優化時間復雜度。接下來我們介紹一個常見的算法,該算法由希臘數學家厄拉多塞提出,稱為厄拉多塞篩法,簡稱埃氏篩。

我們考慮這樣一個事實:如果 x 是質數,那么大於 x 的 x 的倍數 2x,3x,… 一定不是質數,因此我們可以從這里入手。

我們設 isPrime[i] 表示數 i 是不是質數,如果是質數則為 1,否則為 0。從小到大遍歷每個數,如果這個數為質數,則將其所有的倍數都標記為合數(除了該質數本身),即 0,這樣在運行結束的時候我們即能知道質數的個數。

這種方法的正確性是比較顯然的:這種方法顯然不會將質數標記成合數;另一方面,當從小到大遍歷到數 x 時,倘若它是合數,則它一定是某個小於 x 的質數 y 的整數倍,故根據此方法的步驟,我們在遍歷到 y 時,就一定會在此時將 x 標記為 isPrime[x]=0。因此,這種方法也不會將合數標記為質數。

當然這里還可以繼續優化,對於一個質數 x,如果按上文說的我們從 2x 開始標記其實是冗余的,應該直接從 x⋅x ,開始標記, x(x+1), x(x+2)因為 2x,3x,… 這些數一定在 x 之前就被其他數的倍數標記過了,例如 2 的所有倍數,3 的所有倍數等。

 1 class Solution {
 2     public int countPrimes(int n) {
 3         int[] isPrime = new int[n];
 4         Arrays.fill(isPrime, 1);
 5         int res = 0;
 6         for(int i=2; i<n; i++){
 7             if(isPrime[i]==1){
 8                 res+=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 res;
17     }
18 }

 

 

 

 

方法三:線性篩

 

 

 

 

 1 class Solution {
 2     public int countPrimes(int n) {
 3         List<Integer> list = new ArrayList<>();
 4         int[] isPrime = new int[n];
 5         Arrays.fill(isPrime, 1);
 6         for (int i=2; i<n; i++){
 7             if(isPrime[i] == 1){
 8                 list.add(i);
 9             }
10             for (int j=0; j<list.size() && i*list.get(j)<n; j++){
11                 isPrime[i*list.get(j)] = 0;
12                 if(i%list.get(j) == 0){
13                     break;
14                 }
15             }
16         }
17         return list.size();
18     }
19 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM