【问题标题】:Python heapq replace is slower than pop and push?Python heapq replace 比 pop 和 push 慢?
【发布时间】:2022-01-17 03:14:34
【问题描述】:

所以,我想将列表的最大元素减半 k 次。

我用 heapq 实现了它,在将所有内容乘以 -1 后,得到一个最小堆。

def minStoneSum(self, piles: List[int], k: int) -> int:

    h = [-el for el in piles]
    heapq.heapify(h)

    for i in range(k):
        # version 1
        newmax = min(h) >> 1
        heapq.heapreplace(h, newmax)

        # version 2
        # newmax = heapq.heappop(h) >> 1
        # heapq.heappush(h, newmax)
    ...

一开始我是用max()获取第一个项目,heapreplace,因为根据the documentation,他们更快:

heapq.heapreplace(heap, item)
... 这一步操作比 heappop() 后跟 heappush() 更有效,并且在使用固定大小的堆时更合适。

heapq.nsmallest(n, iterable, key=None)
... 另外,当 n==1 时,使用内置的 min() 和 max() 函数效率更高

但是,当我使用较大的初始列表和 k 运行它时,它需要很长时间(超过 30 秒),而当我使用 heappopheappush() 运行版本时,它运行得非常快。

heapreplace 真的比 heappop 和 heappush 慢吗?还是我做错了什么?

【问题讨论】:

    标签: python performance heap


    【解决方案1】:

    似乎heapq.nsmallest 的文档和关于使用min() 的评论一般不是指堆而是指迭代。

    对于堆,最小元素可以通过h[0]找到。

    所以,第一个版本慢得多的原因是因为 min() 将堆视为普通列表,并且(我猜)每次调用使用 O(n)。

    min(h)替换成h[0]后,发现heapreplace确实比调用heappop和heappush快一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-07
      • 2014-01-30
      • 2011-01-10
      • 2016-08-16
      • 2018-04-17
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多