Go 提供了 container/heap 这个包来实现堆的操作。堆实际上是一个树的结构,每个元素的值都是它的子树中最小的,因此根节点 index = 0
的值是最小的,即最小堆。
堆也是实现优先队列 Priority Queue 的常用方式。
堆中元素的类型需要实现 heap.Interface
这个接口:
type Interface interface {
sort.Interface
Push(x interface{}) // add x as element Len()
Pop() interface{} // remove and return element Len() - 1.
}
其中 sort.Interface 包括 Len()
, Less
, Swap
方法:
一个完整的示例如下:
注意注释中的一句话 Push 和 Pop 方法需要使用指针,因为它们会修改 slice 的长度,而不仅仅只内容。
import (
"container/heap"
"fmt"
)
// An IntHeap is a min-heap of ints.
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) {
// Push and Pop use pointer receivers because they modify the slice's length,
// not just its contents.
*h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func main() {
h := &IntHeap{2, 1, 5}
heap.Init(h)
heap.Push(h, 3)
fmt.Printf("minimum: %d\n", (*h)[0]) // minimum: 1
for h.Len() > 0 {
fmt.Printf("%d ", heap.Pop(h)) // 1 2 3 5
}
}
Leetcode 692. Top K Frequent Words 也可以使用 Go 语言通过构造 PriorityQueue 来实现:
type Item struct {
word string
count int
}
type ItemHeap []Item
func (h ItemHeap) Len() int { return len(h) }
func (h ItemHeap) Less(i, j int) bool {
if h[i].count != h[j].count {
return h[i].count < h[j].count
} else {
return h[i].word > h[j].word
}
}
func (h ItemHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *ItemHeap) Push(val interface{}) {
*h = append(*h, val.(Item))
}
func (h *ItemHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func topKFrequent(words []string, k int) []string {
countMap := make(map[string]int)
for _, word := range words {
countMap[word]++
}
h := &ItemHeap{}
for w, v := range countMap {
heap.Push(h, Item{
word: w,
count: v,
})
if h.Len() > k {
heap.Pop(h)
}
}
res := make([]string, h.Len())
for i := h.Len() - 1; i >= 0; i-- {
item := heap.Pop(h).(Item)
res[i] = item.word
}
return res
}
网友评论