python生成器时间复杂度混乱

时间:2016-12-30 18:15:18

标签: python data-structures time-complexity generator

我一直在阅读python中的关键字yield和生成器,我想知道我是否理解它的时间复杂度。

这是我的生成器函数来获取因子:

def calc_factors(n):
    for k in range(0, n+1):     # this is the second "for" loop
        if n % k == 0:
           yield k

我将此生成器函数称为:

>>> for factor in calc_factor(100):   # this is the first "for" loop
        print factor

现在我的理解是,它有时间复杂度O(n ^ 2),因为它有两个for循环,但我再也不相信。请在这方面赐教。 提前谢谢!

2 个答案:

答案 0 :(得分:7)

你误解了。你有一个O(n)循环。生成器函数上的循环不是嵌套循环,它只是在生成器中接收每个项目。

换句话说,for factor in calc_factor(100)循环直接连接yield k表达式;每次执行for factor in calc_factor(100)循环前进一步。对于每个执行的factor表达式,您获得1 yield k个值。 yield k执行(最多)n次,不再执行。

您可以在不过分夸大事实的情况下,将for factor in calc_factor(100)循环体中的所有代码想象为替换 yield k行,factor = k。在您的情况下,您只使用print factor,因此您可以将yield k替换为print k而不会丢失任何功能。

如果您想以不同方式查看它,请取走生成器并构建列表。这就是您的代码在这种情况下所做的事情:

results = []
for k in range(0, n+1):
    if n % k == 0:
       results.append(k)

for factor in results:
    print factor

现在你还有两个循环,但它们没有嵌套。一个是用于构建列表的O(n)循环,另一个是用于打印结果的O(k)循环(具有k O(n))。

所有生成器都是删除中间列表。您不必首先收集所有结果,您可以立即访问每个结果。

答案 1 :(得分:1)

不,这应该只有时间复杂度O(n)。

在一个真正的嵌套循环中,外部循环的每次迭代都会导致内部循环的完整迭代集:

for i in range(100):      # 100 times
    for j in range(i):    # i times, for *each* of the 100 values of i
         # do something

但是在生成器中,yield语句会导致立即从生成器返回控制权。因此,每次迭代生成器时,只计算一个通过生成器的循环。

因此,for factor in calc_factor(100):每个生成器循环的实例都会调用生成器一次。所以从某种意义上说,这个生成器的循环;它只是从发电机本身外部控制的。因此是外部嵌套循环。