LeetCode 204. Count Primes
注:質數從2開始,2、3……
?
改進過程:
一、常規思路是對小于n的每一個數進行isPrime判斷,isPrime(int x)函數中for(int i = 2; i <= x /2; ++i),如果x%i==0,return false。
二、將isPrime(int x)中i的范圍改為i * i <= x。不用i <= sqrt(x),因為sqrt耗時。
三、isPrime中把是2、3、5倍數的數直接return,不進入for循環。
四、對于每一個數p,p2、p2+p、p2+2p……均不為素數,有點像動態規劃的思想。此時可以不用isPrime(int x)函數,而是維護一個isPrime[n]的bool數組,先設里面所有的值均為true,然后i從3開始循環(對應的是如果輸入n<3,直接return 0)。因為會把i2之后的一系列數在isPrime數組中的值變為false,因此i循環至i * i < n。
關于if(!isPrime[i]) continue;這一句解釋一下。如果isPrime[i] == false,那么也就是說在之前的i循環里被標記過了。設之前的循環的數為p,那么 i = p2?+ np,如果沒有continue這一句的話,那么 j = i * i,設j也等于p2 + mp,于是得到等式 (p2?+ np)2 = p2?+ mp,解得m = p((p + n)2 - 1),也就是說j之前在p循環時已經被標記過了,因此可以直接continue,節省時間。以下是代碼,也是題目提示中給出的最優代碼。
1 public int countPrimes(int n) { 2 boolean[] isPrime = new boolean[n]; 3 for (int i = 2; i < n; i++) { 4 isPrime[i] = true; 5 } 6 // Loop's ending condition is i * i < n instead of i < sqrt(n) 7 // to avoid repeatedly calling an expensive function sqrt(). 8 for (int i = 2; i * i < n; i++) { 9 if (!isPrime[i]) continue; 10 for (int j = i * i; j < n; j += i) { 11 isPrime[j] = false; 12 } 13 } 14 int count = 0; 15 for (int i = 2; i < n; i++) { 16 if (isPrime[i]) count++; 17 } 18 return count; 19 }五、在最后計算cnt時,從2開始到n-1都被判斷了一遍,但是偶數絕對不是素數,因此是沒必要訪問其在數組isPrime中的值的。
既然計算cnt時可以跳過偶數,那么在之前的標記isPrime的for循環里,也可以跳過偶數,相應的j每次+= 2 * i,因為p(p + 1)必定為偶數。
所以for循環里依次變為i += 2, j += 2 * i, i += 2(上一步為++i, j += i, ++i)。
?
最終版代碼
1 class Solution { 2 public: 3 int countPrimes(int n) { 4 if(n < 3) return 0; 5 bool* isPrime = new bool [n]; 6 for(int i = 3; i < n; ++i) 7 isPrime[i] = true; 8 9 for(int i = 3; i * i <= n; i += 2){ 10 if(!isPrime[i]) continue; 11 for(int j = i * i; j < n; j += 2 * i) 12 isPrime[j] = false; 13 } 14 15 int cnt = 1; 16 cout<<isPrime[9]<<endl; 17 for(int i = 3; i < n; i += 2){ 18 if(isPrime[i]) ++cnt; 19 } 20 return cnt; 21 } 22 };?
轉載于:https://www.cnblogs.com/co0oder/p/5286781.html
總結
以上是生活随笔為你收集整理的LeetCode 204. Count Primes的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: range函数python-Python
- 下一篇: 哈理工OJ 1289 对数问题