📅  最后修改于: 2023-12-03 15:03:18.467000             🧑  作者: Mango
质数是指只能整除1和本身的自然数。例如,2、3、5、7、11、13等都是质数。已知质数有无数个,但无法给出全部质数。
算法实现:
该算法基于一个简单的想法,如果一个数是质数,则它的倍数一定不是质数。因此,我们可以从数字2开始,将每个质数的倍数标记为非质数。在处理完全部的质数后,所有未被标记成非质数的数字都是质数。
def eratosthenes_sieve(n):
is_prime = [True for i in range(n+1)]
is_prime[0], is_prime[1] = False, False
for i in range(2, int(n**0.5)+1):
if is_prime[i]:
for j in range(i*i, n+1, i):
is_prime[j] = False
primes = []
for i in range(2, n+1):
if is_prime[i]:
primes.append(i)
return primes
print(eratosthenes_sieve(20)) # [2, 3, 5, 7, 11, 13, 17, 19]
和埃拉托斯特尼筛法类似,欧拉筛法也是基于筛选质数倍数的想法。不同之处在于,当处理某个数时,我们可以去除其所有的质数因子,这样可以避免重复标记。
def euler_sieve(n):
is_prime = [True for i in range(n+1)]
primes = []
for i in range(2, n+1):
if is_prime[i]:
primes.append(i)
for p in primes:
if i*p > n:
break
is_prime[i*p] = False
if i % p == 0: # 已经处理完p的倍数
break
return primes
print(euler_sieve(20)) # [2, 3, 5, 7, 11, 13, 17, 19]
线性筛法是欧拉筛法的优化,可以将时间复杂度降至O(n)。该算法和欧拉筛法类似,但是在处理某个数i时,会用其最小质因子p[i]去筛选i*p[j],这样避免了对j=1到i-1的所有非质数进行处理。
def linear_sieve(n):
is_prime = [True for i in range(n+1)]
primes = []
p = [0 for i in range(n+1)]
for i in range(2, n+1):
if is_prime[i]:
primes.append(i)
p[i] = i
for j in range(len(primes)):
if primes[j]*i > n:
break
is_prime[primes[j]*i] = False
p[primes[j]*i] = primes[j]
if i % primes[j] == 0:
break
return primes
print(linear_sieve(20)) # [2, 3, 5, 7, 11, 13, 17, 19]
以上三种算法可以快速地求出小于等于n的所有质数。在实际应用中,我们可以通过查表或者预处理来加速素数的查找。