目錄
- 題目
- 暴力
- 最佳化
- 埃拉託斯特尼素數篩選法
題目
- 輸入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)