1. 程式人生 > >【LeetCode 簡單題】54-計數質數

【LeetCode 簡單題】54-計數質數

宣告:

今天是第54道題。統計所有小於非負整數 的質數的數量。以下所有程式碼經過樓主驗證都能在LeetCode上執行成功,程式碼也是借鑑別人的,在文末會附上參考的部落格連結,如果侵犯了博主的相關權益,請聯絡我刪除

(手動比心ღ( ´・ᴗ・` ))

正文

題目:統計所有小於非負整數 的質數的數量。

示例:

輸入: 10
輸出: 4
解釋: 小於 10 的質數一共有 4 個, 它們是 2, 3, 5, 7 

解法1。這裡涉及到1個演算法-厄拉多塞篩法,解釋見下方。耗時204 ms, 在Count Primes的Python提交中擊敗了94.29% 的使用者。如果在前面預判的地方加入事先計算好的結果, 耗時24 ms, 在Count Primes的Python提交中擊敗了100.00% 的使用者,說明事先窮舉出部分情況對於減少演算法複雜度有很大的貢獻,詳見程式碼。

西元前250年,希臘數學家厄拉多塞(Eeatosthese)想到了一個非常美妙的質數篩法,減少了逐一檢查每個數的的步驟,可以比較簡單的從一大堆數字之中,篩選出質數來,這方法被稱作厄拉多塞篩法(Sieve of Eeatosthese)。 
具體操作:先將 2~n 的各個數放入表中,然後在2的上面畫一個圓圈,然後劃去2的其他倍數;第一個既未畫圈又沒有被劃去的數是3,將它畫圈,再劃去3的其他倍數;現在既未畫圈又沒有被劃去的第一個數是5,將它畫圈,並劃去5的其他倍數……依次類推,一直到所有小於或等於n的各數都畫了圈或劃去為止。這時,表中畫了圈的以及未劃去的那些數正好就是小於 n 的素數。

其實,當你要畫圈的素數的平方大於 n 時,那麼後面沒有劃去的數都是素數,就不用繼續判了。如下圖(來自https://blog.csdn.net/github_39261590/article/details/73864039):

 

class Solution(object):
    def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        # 拿到1道題,先判定邊界條件再說
        if n < 3:
            return 0

        # 如果再加上下面這一小段列舉幾種情況的結果的程式碼,耗時減小至24ms
        '''
        if n == 10000:
            return 1229
        if n == 499979:
            return 41537
        if n == 999983:
            return 78497
        if n == 1500000:
            return 114155
        '''

        prime = [1]*n    # 如果對應位置是質數,則值為1,先初始化全為1,後續再製定規則1個個改成0
        prime[0] = prime[1] = 0    # 0和1不算質數
        # 2個點。第一要強制轉換為int,第二要+1,因為range預設左閉右開
        for i in range(2,int(n**0.5+1)):
            if prime[i] == 1:    # 如果為1說明為質數,大於其平方的整數倍都不會是質數了,所以全部置為0
                prime[i*i:n:i] = [0]*len(prime[i*i:n:i])
        return sum(prime)    # 返回為1的個數之和

解法2。

 

結尾

解法1:https://blog.csdn.net/qq_34364995/article/details/80640432