leetcode-204-計數質數(count primes)-java
阿新 • • 發佈:2018-11-11
題目及用例
package pid204; /* 計數質數 統計所有小於非負整數 n 的質數的數量。 示例: 輸入: 10 輸出: 4 解釋: 小於 10 的質數一共有 4 個, 它們是 2, 3, 5, 7 。 */ import java.util.List; public class main { public static void main(String[] args) { int [] testTable = {15,10,21}; for (int ito : testTable) { test(ito); } } private static void test(int ito) { Solution solution = new Solution(); int rtn; long begin = System.currentTimeMillis(); System.out.print(ito); System.out.println(); //開始時列印陣列 rtn= solution.countPrimes(ito);//執行程式 long end = System.currentTimeMillis(); System.out.println("rtn=" ); System.out.print(rtn); System.out.println(); System.out.println("耗時:" + (end - begin) + "ms"); System.out.println("-------------------"); } }
解法1(失敗,超出時間限制)
死演算法,把每個數mod質數列表,如果沒有mod為0的,則把這個數加入質數列表
package pid204; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; public class Solution { public int countPrimes(int n) { if(n<=2){ return 0; } List<Integer> nums=new ArrayList<>(); int result=1; nums.add(2); boolean isPrime=true; for(int i=2;i<n;i++){ for(Integer now:nums){ if(i%now==0){ isPrime=false; break; } } if(isPrime==true){ nums.add(i); result++; } isPrime=true; } return result; } }
解法2(成功,311ms,超慢)
對上一種方法做了改進,如果質數>該數的開方+1,則不再檢測,少了很多時間
package pid204; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; public class Solution { public int countPrimes(int n) { if(n<=2){ return 0; } List<Integer> nums=new ArrayList<>(); int result=1; nums.add(2); boolean isPrime=true; for(int i=2;i<n;i++){ int mid=(int)Math.sqrt(i)+1; for(Integer now:nums){ if(now>mid){ break; } if(i%now==0){ isPrime=false; break; } } if(isPrime==true){ nums.add(i); result++; } isPrime=true; } return result; } }
解法3(別人的)
使用見埃拉托色尼篩法。
好方法
說的都是對迴圈條件的處理:
如果要實現篩法,需要一個O(n)的陣列來儲存每一個數是不是素數,暫定為true,篩選,把不是素數的定為false,最終數組裡為true的就是所有的素數了。如何篩選?p是素數,那麼2p, 3p……一定不是素數。事實上,如果篩的是2p, 3p……那麼考慮 2*3這個數,它被2篩了一次,又被3篩了一次,沒有必要。可以這樣篩選:對於每一個素數p,篩掉p^{2}, p^{2}+p, p^{2} + 2p……
並不需要對[2, n]的每一個數進行篩選,只需要對[2, \sqrt{n}]進行篩選,即可篩出所有不是素數的數。
class Solution {
public int countPrimes(int n) { //暴力演算法是過不了的qwq
//這個要用篩法實現
boolean[] isPrime = new boolean[n];
int result = 0;
for (int i = 2; i < n; i++) {
isPrime[i] = true; //先初始化為true
}
for (int i = 2; i * i < n; i++) { //這一次for迴圈找出所有不是素數的數(也就是說被篩掉了)
if (!isPrime[i]) {
//既然已經被篩掉了就不用管了
continue;
}
else {
for (int j = i * i; j < n; j += i) {
//由於i現在是一個素數, 那麼i的平方一定不是素數,i^2 + i; i^2 + 2i也一定不是素數
isPrime[j] = false;
}
}
} //所有不是素數的數已經全部篩掉
//計算剩餘的素數個數
for (int i = 2; i < n; i++) {
if (isPrime[i] == true) {
result++;
}
}
return result;
}
}