题目介绍
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
1 <= nums.length <= 105 k 的取值范围是 [1, 数组中不相同的元素的个数] 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/to… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
- 用最小堆思路,先遍历数组,用一个对象numsMap记录每个数字出现的次数
- 遍历numsMap,降每个值压入到最小堆中,如果大于k值,就弹出一个元素,最后堆中的元素就是前k个高频元素
代码
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
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) {
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(nums, k) {
let numsMap = {}
for (let val of nums) {
if (!numsMap[val]) {
numsMap[val] = 1
} else {
numsMap[val] += 1
}
}
let h = new Heap(numsMap)
for (let key in numsMap) {
h.push(key)
if (h.size() > k) {
h.pop()
}
}
return h.data
};