[路飞]_692. 前K个高频单词

122 阅读2分钟

题目介绍

给一非空的单词列表,返回前 k 个出现次数最多的单词。

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

示例 1:

输入: ["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, 2 和 1 次。  

注意:

假定 k 总为有效值, 1 ≤ k ≤ 集合元素数。 输入的单词均由小写字母组成。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/to… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

  1. 求最值的问题,还是用堆的思路解决。求最多单词次数,用小顶堆
  2. 小顶堆类,要实现比较器,用来比较单词次数的大小,大小相同就用单词的Unicode大小比较
  3. 遍历数组,用变量wordsMap记录单词的数量, 在遍历wordsMap把单词放入堆中,如果超过k个弹出堆
  4. 遍历结束,需要对堆的数据根据单词数量从大到小排序,如果数量相同就根据Unicode大小比较排序
/**
 * @param {string[]} words
 * @param {number} k
 * @return {string[]}
 */
class Heap {
  constructor(mapVal) {
    this.data = []
    this.mapVal = mapVal
  }
  // 向下调
  shiftDown(ind = 0) {
    let n = this.size() - 1
    while (ind * 2 + 1 <= n) {
      let tmp = ind
      // 小顶堆是用大于号 this.data[tmp] > this.data[ind * 2 + 1], 大顶堆小于号 this.data[tmp] < this.data[ind * 2 + 1]
    if (this.cmp(this.data[tmp], this.data[ind * 2 + 1])) tmp = ind * 2 + 1
    //   if (this.getVal(this.data[tmp]) > this.getVal(this.data[ind * 2 + 1])) tmp = ind * 2 + 1
    if (ind * 2 + 2 <= n && this.cmp(this.data[tmp], this.data[ind * 2 + 2])) tmp = ind * 2 + 2
      if (tmp === ind) break
      this.data[tmp] = [this.data[ind], (this.data[ind] = this.data[tmp])][0]
      ind = tmp
    }
  }
  getVal(key) {
      return this.mapVal[key]
  }
  cmp(key1, key2) {
      if (this.getVal(key1) - this.getVal(key2)) return this.getVal(key1) > this.getVal(key2)
      return key1 < key2
  }
  // 向上调整
  shiftUp(idx) {
    let pIdx = null
    while (
      ((pIdx = Math.floor((idx - 1) / 2)),
      // 小顶堆是用大于号 this.data[pIdx] > this.data[idx], 大顶堆用小于号this.data[pIdx] < this.data[idx]
      idx && this.cmp(this.data[pIdx], this.data[idx]))
    ) {
      this.data[pIdx] = [this.data[idx], (this.data[idx] = this.data[pIdx])][0]
      idx = pIdx
    }
  }
  push(val) {
    this.data.push(val)
    this.shiftUp(this.size() - 1)
  }
  pop() {
    if (this.size() === 0) return
    if (this.size() === 1) {
      return this.data.pop()
    }
    this.data[0] = this.data.pop()
    this.shiftDown(0)
  }
  top() {
    return this.data[0]
  }
  size() {
    return this.data.length
  }
}
var topKFrequent = function(words, k) {
    let wordsMap = {}
    for (let val of words) {
        if (!wordsMap[val]) {
            wordsMap[val] = 1
        } else {
            wordsMap[val] += 1
        }
    }
    let h = new Heap(wordsMap)
    for (let key in wordsMap) {
        h.push(key)
        if (h.size() > k) {
            h.pop()
        }
    }
    h.data.sort((a, b) => {
        if (wordsMap[b] - wordsMap[a]) {
           return wordsMap[b] - wordsMap[a]
        }
        return a < b ? -1 : 1
    })
    return h.data
};