Eratosthenes的筛子设置 - 实施混乱

时间:2015-10-20 01:14:03

标签: python sieve-of-eratosthenes

我想首先说明我是一个蟒蛇新手,而且我对任何能够清楚而完整地向我解释它的人都很慷慨。

我正在查看以下链接中的代码:

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))时间?

2 个答案:

答案 0 :(得分:1)

最后一行:

multiples.update(range(i*i, n+1, i))

i的平方i的所有倍数n添加到集合multiplesi平方下方的任何倍数都将位于较早i的集合中。

Rosetta并没有说算法是O(log(n)),它肯定不是,但只是集合查找是O(log(n))vs list O(n)。原因是集合使用散列作为查找的手段,实际上是平均O(1)对O(n)

答案 1 :(得分:1)

表达式range(i, j, k)生成从ij的整数列表(j不包含,因此包含范围为j-1 ),间隔为k(默认为1)。因此range(2, 10, 2)生成列表[2, 4, 6, 8]

最后一行正在做的是将i 2 的所有倍数i插入到nmultiples集。我们从i 2 开始,因为i是素数(因为它没有在筛子中找到),而i的下一个最小倍数不在multiplesi×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,这样可以在空间成本方面获得更好的效果。