Go学习打卡Day08 数据结构—堆

138 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

Go学习打卡Day08 数据结构—堆

1、堆的定义与实现

package main
​
import (
    "container/heap"
    "fmt"
)
​
type IntHeap []intfunc main() {
    h := &IntHeap{2, 1, 3}
    heap.Init(h)
    heap.Push(h, 4)
    heap.Push(h, 5)
    fmt.Printf("min value : %d\n", (*h)[0])
    fmt.Printf("heap len : %d\n", h.Len())
    for h.Len() > 0 {
        fmt.Printf("%d ", heap.Pop(h))
    }
}
​
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{}) {
    *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
}
​

692. 前K个高频单词

给定一个单词列表 words 和一个整数 k ,返回前 k个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按 字典顺序 排序。

  • 示例 1:
输入: words = ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i""love" 为出现次数最多的两个单词,均为2次。
    注意,按字母顺序 "i""love" 之前。
  • 示例 2:
输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
输出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny""day" 是出现次数最多的四个单词,
    出现次数依次为 4, 3, 21 次。
  • 注意:
1 <= words.length <= 500
1 <= words[i] <= 10
words[i] 由小写英文字母组成。
k 的取值范围是 [1, 不同 words[i] 的数量]

解题思路:

  • 采用优先队列(堆)。优先队列可以在 O(logn)的时间内完成插入或删除元素的操作;
  • 创建一个小根优先队列,我们将每一个pair(字符串以及出现的次数)插入到优先队列中,如果优先队列的大小超过了 k,就将优先队列顶端元素弹出。这样最终优先队列中剩下的 k个元素就是前 k 个出现次数最多的单词。

代码如下:

func topKFrequent(words []string, k int) []string {
    mp := map[string]int{}
    for _, v := range words {
        mp[v]++
    }
    h := &hp{}
    for w, v := range mp {
        heap.Push(h, pair{w, v})
        if h.Len() > k {
            heap.Pop(h)
        }
    }
    ret := make([]string, k)
    for i := k - 1; i >= 0; i-- {
        ret[i] = heap.Pop(h).(pair).w
    }
    return ret
}
​
type pair struct {
    w string
    c int
}
type hp []pair
func (h hp) Len() int            { return len(h) }
func (h hp) Less(i, j int) bool  { a, b := h[i], h[j]; return a.c < b.c || a.c == b.c && a.w > b.w }
func (h hp) Swap(i, j int)       { h[i], h[j] = h[j], h[i] }
func (h *hp) Push(v interface{}) { *h = append(*h, v.(pair)) }
func (h *hp) Pop() interface{}   { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
​