堆与优先队列:Top-K 与合并问题的底座

排序能做 Top-K,但堆通常更省;合并 K 个有序表时,堆几乎是标配。

二叉堆维护「堆顶最优」:小根堆顶是最小,大根堆顶是最大。插入与删除堆顶均摊 O(log n)。

Top-K 套路

求最大的 K 个:维持容量为 K 的小根堆;超过 K 时与堆顶比较,更大则替换。结束后堆内即答案。

// 思路:小根堆存当前 Top-K
for _, x := range nums {
    if h.Len() < k {
        heap.Push(h, x)
    } else if x > (*h)[0] {
        (*h)[0] = x
        heap.Fix(h, 0)
    }
}

Go 中的接口

container/heap 要求实现 Len/Less/Swap/Push/Pop。Less 决定堆序;业务字段比较写在 Less 里即可。

小结

看见「第 K」「合并多路有序」或「动态取最值」,优先想到堆。先确定大根还是小根,再写 Push/Pop。