[LeetCode] 204. 計數質數:JavaScript 實現埃拉託斯特尼篩法

題目連接leetcode-cn.com/problems/co…javascript

看到這個題目,通常人很容易就能想到使用循環,經過暴力遍歷的方式檢查每個數是否爲質數,並進行計數。html

可是這種方法的算法複雜度太高,對於小範圍搜索還好,若是是從百萬甚至千萬的數字中找出全部的質數,這種方法的劣勢將極其明顯。那咱們可使用埃拉託斯特尼篩法進行質數的查找。java

埃拉託斯特尼篩法

埃拉託斯特尼篩法,簡稱埃氏篩,也稱素數篩。這是一種簡單且歷史悠久的篩法,用來找出必定範圍內全部的素數。所使用的原理是從 2 開始,將每一個素數的各個倍數,標記成合數。git

一個素數的各個倍數,是一個差爲此素數自己的等差數列。此爲這個篩法和試除法不一樣的關鍵之處,後者是以素數來測試每一個待測數可否被整除。github

埃拉託斯特尼篩法是列出全部小素數最有效的方法之一,其名字來自於古希臘數學家埃拉託斯特尼,而且被描述在另外一位古希臘數學家尼科馬庫斯所著的《算術入門》中。算法

本算法的核心思想是:給出要篩選數值的範圍 n,找出 √𝑛 之內的素數 p1, p2..., p𝑘。先用 2 去篩,即把 2 留下,把 2 的倍數剔除掉;再用下一個素數,也就是 3 篩,把 3 留下,把 3 的倍數剔除掉;接下去用下一個素數 5 篩,把 5 留下,把 5 的倍數剔除掉;不斷重複下去……微信

以下圖所示:測試

下面是本算法的實現代碼:ui

/** * @param {number} n * @return {number} */
var countPrimes = function(n) {
    let count = 0;
    let signs = new Uint8Array(n);

    for (let i = 2; i < n; i++) {
        if (!signs[i - 1]) {
            count++;

            for (let j = i * i; j <= n; j += i) {
                signs[j - 1] = true;
            }
        }
    }
    return count;
};
複製代碼

√ Acceptedspa

  • 20/20 cases passed (76 ms)
  • Your runtime beats 99.23 % of javascript submissions
  • Your memory usage beats 86.67 % of javascript submissions (36.9 MB)
  • 時間複雜度:O(n * loglog n)
  • 空間複雜度:O(n)

參考資料:

更多題解

請關注:github.com/leviding/le…

本人水平有限,歡迎交流分享你的想法,歡迎大佬批評指正。


掃描下方二維碼,關注微信公衆號「技術漫談」,訂閱更多精彩內容。

相關文章
相關標籤/搜索