leetcode演算法題-計數質數
阿新 • • 發佈:2021-01-07
題目
本題為leetcode探索初級演算法中數學章節的一題
統計所有小於非負整數 n 的質數的數量。
示例:
輸入: 10
輸出: 4
解釋: 小於 10 的質數一共有 4 個, 它們是 2, 3, 5, 7 。
作者:力扣 (LeetCode)
連結:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnbcaj/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
我的解法
看了題目感覺挺簡單于是:
class Solution { public int countPrimes(int n) { int result = 0; for (int i = 2; i < n; i++) { boolean is = true; for (int j = 2; j <= i; j++){ if(i != j && i % j == 0){ is = false; break; } } if(is){ result ++; } } return result; } }
執行的時候超出了限制。尷尬。
優化版
class Solution { public int countPrimes(int n) { int result = 0; for (int i = 2; i < n; i++) { if(isPrime(i)){ result ++; } } return result; } public boolean isPrime(int num) { if (num <= 3) { return num > 1; } // 不在6的倍數兩側的一定不是質數 if (num % 6 != 1 && num % 6 != 5) { return false; } int sqrt = (int) Math.sqrt(num); for (int i = 5; i <= sqrt; i += 6) { if (num % i == 0 || num % (i + 2) == 0) { return false; } } return true; } }
主要優化了判斷質數的邏輯,根據質數的規律優化了判斷。
執行用時: 236 ms,記憶體消耗: 35.6 MB。
但是執行時間還是太長。
題解版-厄拉多塞篩法
class Solution { public int countPrimes(int n) { int result = 0; boolean[] b = new boolean[n]; // 初始化預設值都為 false,為質數標記 if(2 < n) result++; // 如果大於 2 則一定擁有 2 這個質數 for(int i = 3; i < n; i += 2){ // 從 3 開始遍歷,且只遍歷奇數 if(!b[i]){ // 是質數 for(int j = 3; i * j < n; j += 2){ b[i * j] = true; // 將當前質數的奇數倍都設定成非質數標記 true } result++; // 質數個數 +1 } } return result; } }
利用長度為n的陣列記錄是否質數的結果。
當a不是質數時,將小於n的且是a的倍數的數字設定為不是質數。
雖然多了額外的空間開銷但是耗時僅10ms,快了20多倍。
ps:若n非常大時,可以考慮點陣圖等替換陣列。