题目介绍
给一非空的单词列表,返回前 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… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
- 求最值的问题,还是用堆的思路解决。求最多单词次数,用小顶堆
- 小顶堆类,要实现比较器,用来比较单词次数的大小,大小相同就用单词的Unicode大小比较
- 遍历数组,用变量wordsMap记录单词的数量, 在遍历wordsMap把单词放入堆中,如果超过k个弹出堆
- 遍历结束,需要对堆的数据根据单词数量从大到小排序,如果数量相同就根据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
};