堆与优先队列: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。