我一直在阅读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循环,但我再也不相信。请在这方面赐教。 提前谢谢!
答案 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
所有生成器都是删除中间列表。您不必首先收集所有结果,您可以立即访问每个结果。
答案 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):
每个生成器循环的实例都会调用生成器一次。所以从某种意义上说,这个是生成器的循环;它只是从发电机本身外部控制的。因此不是外部嵌套循环。