计数质数
目录
计数质数
https://leetcode-cn.com/problems/count-primes/
一开始直接暴力,隐约感觉会超时,果然不出我所料
class Solution:
def countPrimes(self, n: int) -> int:
= 0
counts for i in range(n):
if self.isprime(i):
+= 1
counts return counts
def isprime(self,n):
from itertools import count
if n <=1:
return False
for i in count(2):
if i* i > n:
return True
if n % i == 0:
return False
我还特意用了itertools库,没想到还是超时了
埃氏筛
class Solution:
def countPrimes(self, n: int) -> int:
= [1] * n
res = 0
count for i in range(2, n):
if res[i]:
+= 1
count for j in range(i*i, n, i):
= 0
res[j] return count
埃氏筛的原理:从 2 开始,将每个质数的倍数都标记为合数。同样的,标记到 根号n停止。
假设一个数 i 为质数时,那么此时大于 i 且是 i 的倍数的数一定不是质数,例如 2i,3i…。那么我们将这些不是质数的数进行标记。
这里需要注意,标记应该从 i * i 开始,而不是 2 * i 开始。因为对于每个数 i 来说,枚举是从小到大的,此时前面数字的倍数都已经进行了标记。对于 i 而言,2∗i 也肯定会被在枚举数字 2 时进行标记,[2, i) 区间的数同理。
欧拉筛(线性筛)
具体的证明不说了,背板子就行
class Solution:
def countPrimes(self, n: int) -> int:
if n <= 1:
return 0
= [True] * n
is_prime
0] = is_prime[1] = False
is_prime[
= []
res
for i in range(2, n):
if is_prime[i]:
res.append(i)
= 0
j
while j < len(res) and (tmp:=i*res[j]) < n:
= False
is_prime[tmp]
if i % res[j] == 0: # 如果res[j]为当前数的约数,则i*res[j+1]等后面的数必然会在后面的计算得到。就结束循环。这减少了重复计算。
break
+= 1
j
return len(res)