如何高效尋找素數

Frommoon發表於2024-03-04

目錄
  • 題目
  • 暴力
  • 最佳化
  • 埃拉託斯特尼素數篩選法

題目

  • 輸入n,返回[2,n)中素數的個數

暴力

  • 從2開始到n,一個一個判斷是不是素數,是的話就計數器加1。判斷素數函式:從2開始到n,判斷有沒有是n的倍數,有倍數就不是素數
def countPrimes(n:int):
    count=0
    for i in range(2,n):
        if (isPrimes(i)):
            count+=1
    return count
def isPrimes(n:int):
    for i in range(2,n):
        if n%i==0:#如果這個數從2開始到自己都沒有一個是倍數,則是素數
            return False
    return True
if __name__ == "__main__":
    n=int(input())
    print(countPrimes(n))
  • 時間複雜度o(n^2)

最佳化

  • 判斷素數函式中for迴圈範圍改變了,因為:比如n=12,我們只需要判斷26,不需要判斷62,中間是以根號n分開的,所以我們判斷素數時,只需要判斷[2,根號n)
import math
def countPrimes(n:int):
    count=0
    for i in range(2,n):
        if (isPrimes1(i)):
            count+=1
    return count
def isPrimes1(n:int):
    for i in range(2,int(math.sqrt(n))+1):
        if n%i==0:#如果這個數從2開始到自己都沒有一個是倍數,則是素數
            return False
    return True
if __name__ == "__main__":
    n=int(input())
    print(countPrimes(n))
  • 時間複雜度o(sqrt(n))

埃拉託斯特尼素數篩選法

  • 先初始化陣列全為True,然後把是素數的倍數全部刪去,最後統計陣列中是True的個數返回
import math
def countPrimes1(n: int) -> int:
    isPrime = [True for i in range(n)]  # 初始化陣列為全 True,表示所有數都是質數
    for i in range(2, int(math.sqrt(n)) + 1):#乘法因子的對稱性
        if isPrime[i]:#是素數的情況下,把他的倍數全部刪去
            for j in range(i*i, n, i):#從i*i開始,到n以i為步長,都是i的倍數,全置為False
                isPrime[j] = False
    count = 0
    for i in range(2, n):
        if isPrime[i]:#統計isPrime陣列中是ture的個數
            count += 1
    return count
if __name__ == "__main__":
    n=int(input())
    print(countPrimes1(n))
  • 時間複雜度o(NloglogN)

相關文章