Eratosthenes 筛法是一种相当快的生成素数的方法,其限制k
如下:
- 从集合
p = (2, 3, 4, ..., k)
和开始i = 2
。 - 从 开始,删除from
i^2
的所有倍数。i
p
- 重复下一个最小
i
的p
,直到i >= sqrt(k)
。
我当前的实现看起来像这样(对预过滤所有偶数进行了明显的优化):
# Compute all prime numbers less than k using the Sieve of Eratosthenes
def sieve(k):
s = set(range(3, k, 2))
s.add(2)
for i in range(3, int(sqrt(k)), 2):
if i in s:
for j in range(i ** 2, k, i * 2):
s.discard(j)
return sorted(s)
编辑:这是基于等效list
的代码:
def sieve_list(k):
s = [True] * k
s[0] = s[1] = False
for i in range(4, k, 2):
s[i] = False
for i in range(3, int(sqrt(k)) + 2, 2):
if s[i]:
for j in range(i ** 2, k, i * 2):
s[j] = False
return [2] + [ i for i in range(3, k, 2) if s[i] ]
这有效,但并不完全正确。这些行:
for i in range(3, int(sqrt(k)), 2):
if i in s:
[...]
s
通过测试每个奇数的集合成员关系找到下一个最小元素。理想情况下,实现实际上应该是:
while i < sqrt(k):
[...]
i = next smallest element in s
但是,由于set
是无序的,我不知道如何(或者即使可能)以更有效的方式获得下一个最小元素。我考虑过使用list
带有True
/False
标志的素数,但您仍然必须步行list
寻找下一个True
元素。您不能只从其中list
任何一个中实际删除元素,因为这使得在步骤 2 中有效地删除复合数字成为不可能。
有没有办法更有效地找到下一个最小的元素?如果没有,是否有其他数据结构允许O(1)
按值删除以及找到下一个最小元素的有效方法?