【发布时间】:2020-04-15 13:22:07
【问题描述】:
我正在创建一个 Eratosthenes 筛子,以便更有效地对 1 和大数 n 之间的素数求和。我要做的是创建一个从2到n的列表,然后删除2的倍数,然后是3的倍数,然后是列表中下一个数字的倍数,依此类推。我创建的代码我认为它在时间上的性能非常慢,这几乎就像通过检查每个条目是否是质数来创建一个列表。我猜我的操作数量是有序的: n 的平方根(第一个 while 循环)乘以(略小于)n 的平方根(对于第二个 while 循环)。所以我不确定删除方法或其他方法是否会减慢它的速度。
我的代码是这个:
def sieve_of_Eratosthenes(n):
L= list(range(2,n+1))
# creates a list from 2 to n
i=2
while i*i <=n: # going to remove multiples of i, starting at i^2
k=i # if j <i then ij already checked
while i*k <= max(L):
try:
L.remove(i*k) # there is an error if the element is not in
# the list so need to add these two lines
except ValueError:
pass # do nothing!
k=k+1
i=L[i-1] # list index starts at 0, want i to be next element in the list
# print(L)
return L
【问题讨论】:
-
有很多实现贴here
-
删除是罪魁祸首,它破坏了直接可索引性。不得删除,而是标记而不删除。删除按值删除,因此必须扫描列表,因此每次删除都是 O(n); O(1) 按索引标记是目标,也是整体速度的前提。
-
@WillNess 这就是我正在寻找的答案!谢谢
-
自相矛盾,一些移除不是 O(n),所以这些移除是好的。有些是 O(1)(哈希表)有些是 O(log n)(来自树,或者在合并排序的递增的倍数列表时),这是可以容忍的。
-
这里说从列表中删除一个元素是 O(n) wiki.python.org/moin/TimeComplexity
标签: python performance primes