foo*_*foo 18 python algorithm heap time-complexity
我正在看这个pycon谈话,34:30,发言人说,获取t
元素列表中最大的n
元素可以完成O(t + n)
.
怎么可能?我的理解是创建堆将是O(n)
,但nlargest
它本身的复杂性是它O(n + t)
还是O(t)
(以及实际算法是什么)?
Tim*_*ers 21
在这种情况下,发言者是错误的.实际成本是O(n * log(t))
.仅在t
可迭代的第一个元素上调用Heapify .那是O(t)
,但如果t
小得多,那就微不足道了n
.然后,所有剩余的元素一次一个地添加到这个"小堆"中heappushpop
.O(log(t))
每次调用都需要时间heappushpop
.堆的长度始终存在t
.在最后,堆被分类,这是成本O(t * log(t))
,但如果t
比小得多,这也是微不足道的n
.
有一些相当简单的方法可以在预期的O(n)
时间内找到第t个最大元素; 例如,请看这里.在最坏的情况下,有更难的方法O(n)
.然后,在输入的另一个传递中,您可以输出t
元素> =第t个最大(在重复的情况下具有繁琐的复杂性).所以整个工作都可以及时完成O(n)
.
但这些方式也需要O(n)
记忆.Python不使用它们.实际实现的优点是最坏情况下的"额外"内存负担O(t)
,并且当输入是例如产生大量值的发生器时,这可能是非常重要的.
对于 Heapq t 最大或 t 最小,时间复杂度为O(nlog(t))
Heapq 将为前 t 个元素构建堆,然后它将通过从堆中压入和弹出元素(在堆中维护 t 元素)来迭代剩余元素。
tlog(t)
(n-t)log(t)
nlog(t)