题目:
给定一个单词列表 words 和一个整数 k ,返回前 k **个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。
算法: 有排序和和heap两种实现。heap法注意: 1.less方法要根据单词频率和单词字典序 2.返回结果时要按照每次remove()的方法取。不能直接返回heap.Array数组。
func topKFrequent(words []string, k int) []string {
wordsNum := make(map[string]int)
for i := range words {
wordsNum[words[i]] ++
}
heap := NewHeap(k)
for word, num := range wordsNum {
heap.Add(WordNum{word:word, num:num})
}
ans := make([]string, heap.N)
// 逆序输出
for i := heap.N; i > 0; i -- {
wn := heap.remove()
ans[i - 1] = wn.word
}
return ans
}
type WordNum struct {
word string
num int
}
type Heap struct{
Array []WordNum
N int
Capacity int
}
func NewHeap(n int) *Heap{
return &Heap{
Array: make([]WordNum, 1),
Capacity: n,
}
}
func (h *Heap)Add(v WordNum){
if h.N < h.Capacity {
h.insert(v)
} else if h.Array[1].num < v.num || (h.Array[1].num == v.num && h.Array[1].word > v.word ){
h.insert(v)
h.remove()
}
}
func (h *Heap)insert(v WordNum){
h.N ++
h.Array = append(h.Array, v)
h.swim(h.N)
}
// pop掉第一个元素
func (h *Heap) remove() WordNum{
res := h.Array[1]
h.Array[1], h.Array[h.N] = h.Array[h.N], h.Array[1]
h.Array = h.Array[:h.N]
h.N --
h.sink(1)
return res
}
// less(i, parent)==true时,执行swim,节点i上浮,
func (h *Heap)sink(i int){
child := 2 * i
if child + 1 < len(h.Array) && h.less(child + 1, child) {
child = child + 1
}
if child < len(h.Array) && h.less(child, i) {
h.Array[i], h.Array[child] = h.Array[child], h.Array[i]
h.sink(child)
}
}
// less(i, parent)==true时,执行swim,节点i上浮,
func (h *Heap)swim(i int){
// fmt.Println("swim", h.Array, i)
parent := i / 2
if 0 < parent && h.less(i, parent) {
h.Array[i], h.Array[parent] = h.Array[parent], h.Array[i]
h.swim(parent)
}
}
func (h *Heap)less(i int, j int) bool {
return h.Array[i].num < h.Array[j].num || h.characterless(i, j)
}
func (h *Heap)characterless(i int, j int) bool {
return h.Array[i].num == h.Array[j].num && h.Array[i].word > h.Array[j].word
}
func (h *Heap)swap(i int, j int) {
h.Array[i], h.Array[j] = h.Array[j], h.Array[i]
}