我正在查看this pycon talk, 34:30,发言人表示,t
可以在n
内完成O(t + n)
元素列表的O(n)
个最大元素。
怎么可能?我的理解是创建堆将是nlargest
,但O(n + t)
本身的复杂性是什么,是O(t)
还是{{1}}(以及实际算法是什么)?
答案 0 :(得分:14)
在这种情况下,发言人是错误的。实际费用为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个最大的元素;例如,see here。在最坏情况O(n)
时间内,有更难的方法。然后,在输入的另一个传递中,您可以输出t
元素> =第t个最大(在重复的情况下具有繁琐的复杂性)。因此整个工作可以在O(n)
时间内完成。
但这些方式也需要O(n)
内存。 Python不使用它们。实际实施的一个优点是最坏的情况"额外的"内存负担是O(t)
,当输入是一个产生很多值的生成器时,这可能非常重要。
答案 1 :(得分:0)
它实际上是 O(n+tlog(n)) 因为 heapify 需要 O(n) 并且对于最大或最小的每个元素都需要 O(log(n))。所以对于 t 最大/最小它需要 tlog(n)。因此时间复杂度为 O(n+t*log(n))