寻找质数的算法时间复杂度
我对质数很感兴趣,想知道在比如说1000万这个范围内,找到相对较小的质数最有效的方法是什么。我听说埃拉托斯特尼筛法(SOE)是找小质数最有效的方式。我用Python实现了这个算法,但有几个问题:
我的算法在最坏情况下的运行时间似乎是O(n^2)。我还在学习中,所以我知道这个算法可以更高效。
在寻找质数时,最有效的数学方法和最有效的编程方法有什么区别吗?从数学上讲,SOE是最快的之一,但从编程的角度来看,SOE真的那么快吗?
def FindPrime(n):
primes = [2, 3]
for num in range(4, n):
notprime = False
for p in primes:
if num % p == 0:
notprime = True
if notprime == False:
primes.append(num)
print primes
print FindPrime(100)
2 个回答
0
uʍop ǝpısdn 说得对,你的代码不是最优的素数筛选算法(SOE)
你可以在这里找到我实现的素数筛选算法 这里
- 这个实现比你的方案更高效
我这个素数筛选算法的复杂度
- 时间复杂度是
T(0.5·n·DIGAMMA(CEIL(SQRT(n))+0.3511·n)
,如果按照代码里的建议使用平方根(N) - 当 n=1M 时,时间复杂度是
T(3.80*n)
- 当 n=10M 时,时间复杂度是
T(4.38*n)
- 当 n=100M 时,时间复杂度是
T(4.95*n)
- 当 n=1000M 时,时间复杂度是
T(5.53*n)
- 所以大致的运行时间是:
T((0.3516+0.5756*log10(n))*n)
- 因此复杂度是
O(n.log(n))
- 时间复杂度是
运行速度(运行时间)和复杂度 O() 的区别
- 实际的运行时间是
t=T(f(n))*c
- 当 n 足够大时,它会收敛到
t=O(f(n))*c
- 其中
O()
是算法的时间复杂度 - 而
T()
是任何 n 的实际运行时间公式(不是O()
!!!) - 这里的
c
是处理所有for
循环的单次处理所需的常数时间等等... - 更好的
O()
并不意味着更快的解决方案 - 对于任何
n
,只有在阈值之后 O1(f1(n))*c1 < O2(f2(n))*c2
- 所以如果你能很好地优化
c
常数,那么你可以在某个阈值之前超越更好的复杂度算法 - 例如你的代码大约是
T(n.n/2)
->O(n^2)
- 但在小的 n 时可能比我的素数筛选算法
O(n.log(n))
更快 - 因为我的算法需要准备表格,这在某个点上会比你的除法花更多时间
- 但之后你的算法会变得慢得多...
- 实际的运行时间是
所以对于是否存在最有效的数学和编程解决方案之间的差异
- 答案是 是的,在定义的 N 范围内可能存在差异