我想首先说明我是一个蟒蛇新手,而且我对任何能够清楚而完整地向我解释它的人都很慷慨。
我正在查看以下链接中的代码:
http://rosettacode.org/wiki/Sieve_of_Eratosthenes#Python
我刚开始理解迭代器,生成器和yield命令,但我不了解代码如何适用于set实现。
def eratosthenes2(n):
multiples = set()
for i in range(2, n+1):
if i not in multiples:
yield i
multiples.update(range(i*i, n+1, i))
我很难理解这个函数的最后一行是什么。
此外,有人可以向我解释为什么这个实现是O(log(n))时间?
答案 0 :(得分:1)
最后一行:
multiples.update(range(i*i, n+1, i))
将i
的平方i
的所有倍数n
添加到集合multiples
。 i
平方下方的任何倍数都将位于较早i
的集合中。
Rosetta并没有说算法是O(log(n)),它肯定不是,但只是集合查找是O(log(n))vs list O(n)。原因是集合使用散列作为查找的手段,实际上是平均O(1)对O(n)
答案 1 :(得分:1)
表达式range(i, j, k)
生成从i
到j
的整数列表(j
不包含,因此包含范围为j-1
),间隔为k
(默认为1)。因此range(2, 10, 2)
生成列表[2, 4, 6, 8]
。
最后一行正在做的是将i
2 的所有倍数i
插入到n
到multiples
集。我们从i
2 开始,因为i
是素数(因为它没有在筛子中找到),而i
的下一个最小倍数不在multiples
为i
×i
。证明:如果对于某些c,i
的下一个最小倍数是等于c×i
的值,其中1 <1。 c&lt; i
,那么我们已经将它过滤掉了。我们在n+1
结束范围,因为筛子结束的地方(1弥补了结束界限是非包容性的)。当然,我们的间隔设置为i
以产生其倍数。
关于O(log(n))的位是指在公共集实现中测试集成员资格的时间复杂度,而不是完整算法。整个算法的复杂性不能小于O(n),因为外循环运行n
- 1次(从2到n)。实际上,由于Python集是哈希表,因此集合成员测试需要O(1)时间。或者,您可以使用list
n
bool
,这样可以在空间成本方面获得更好的效果。