1. 程式人生 > 實用技巧 >leetcode演算法題-計數質數

leetcode演算法題-計數質數

題目

本題為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非常大時,可以考慮點陣圖等替換陣列。