題目連接: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)
參考資料:
本人水平有限,歡迎交流分享你的想法,歡迎大佬批評指正。
掃描下方二維碼,關注微信公衆號「技術漫談」,訂閱更多精彩內容。