質數記數演算法:埃拉託斯特尼篩法
阿新 • • 發佈:2022-02-12
質數計數演算法:埃拉託斯特尼篩法
前置知識:質數(素數)是指:在大於1的自然數中,除了1和它本身以外不再有其他因數的自然數。在判斷一個數是否為質數時,常用的方法為:從2開始,遍歷到\(\sqrt n\),如果沒有可以整除的,則n是質數;反之,如果找到可以整除的,n就為合數.(對於大多數的暴力解法,也大多采用這種求法)
方法介紹
埃拉託斯特尼篩法是一種非常巧妙的經典演算法。基本思想是:如果找到一個質數,那麼對於這個質數的倍數就必定不是質數。所以,如果需要在一個範圍[0,n]找到所有質數,那麼我們只需要把不大於\(\sqrt n\)的所有質數的倍數取出,剩下的一定是質數,這就是篩法。
例如,對於質數7來說,它的倍數14,21,28等都一定不是質數,如果按照之前的暴力求解演算法,那麼我們在驗證質數的時候,在這裡就會進行一次多餘的驗證。按照埃拉託斯特尼篩法的思想,驗證到一個質數時,我們就可以同時把它的倍數也篩選出去。
通常來說,一開始會建立兩個列表(例如陣列),一個用於存放所有待檢查的數字,稱為數字列表(包含質數和合數),另外一個用來存放已經發現的質數,稱為質數列表。篩法的第一步是將數字列表中的第一個數字刪除,把它新增到質數列表中(因為1不在定義範圍之中,所以這裡的第一個數是2),隨後檢查數字列表中所有2的倍數全部刪除。之後再將數字列表中的第一個數刪除,新增到質數列表中,同時在數字列表中刪除倍數,迴圈操作直到數字列表為空。
方法改進
- 首先,因為所有的偶數都是2的倍數(好像是個廢話),所以在開始生成數字列表的時候就可以只生成奇數,這樣一來列表大小就就可以縮小一半
- 當數字列表中的首個元素的值大於最大數字的平方根的時候,演算法就可以停止了。
- 另外還有一種取巧的方法,使用單獨的布林陣列,將索引作為自然數,true表示是質數,false表示不是質數,這樣就可以節省一個記憶體空間。
程式碼實現可以參考百度:埃拉託斯特尼篩法_百度百科
關聯題目
Leetcode :204.計數質數
洛谷:P5723 質數口袋