携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情
前k个高频元素
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
来源:力扣(LeetCode) 链接:leetcode.cn/problems/to…
分析
Hash Map
- 根据题意,比较容易想到对数组进行遍历,生成一个元素出现次数数组,找出前k个高频的元素也就是数组按照出现次数从大到小取前k个即可得到答案
代码
var topKFrequent = function(nums, k){
let map = new Map()
for(let i=0;i<nums.length;i++){
if(map.has(nums[i]){
map.set(nums[i],map.get(nums[i])+1)
} else {
map.set(nums[i],1)
}
}
let values = map.values()
let keys = map.keys()
let res = []
for(let j=0;j<k;j++){
let index = values.indexOf(Math.max(...values))
value[index] = null
res.push(keys[index])
}
return res
}
数组自动排序
- 在遍历数组的时候,自动对数组进行排序,直接去排好序数组的最大k个
代码
var topKFrequent = function(nums, k){
let arr = []
let sort = []
let res = []
for(let i=0;i<nums.length;i++){
arr[nums[i]] = (arr[nums[i]] || 0) + 1
}
for(let item in arr){
sort[arr[item]] ? sort[arr[item]].push(item) : sort[arr[item]] = [item]
}
for(let i = sort.length -1 ;i>=0;i--){
if(sort[i]){
res.push(...sort[i])
}
}
return res
}
小顶堆
- 使用堆来遍历出现次数数组,当堆内元素小于k,直接插入堆中,如果堆内个数等于k,检查堆顶与当前遍历值出现的次数谁大,如果堆顶大,说明有至少k个数字的出现次数比当前遍历到的次数大,舍弃当前的值,反之就插入堆中,遍历后,堆中的元素就是前k个高频元素
代码
var topKFrequent = function(nums, k) {
let freq = {}, heap = [];
let left = i => i * 2 + 1 < k ? i * 2 + 1 : i;
let right = i => i * 2 + 2 < k ? i * 2 + 2 : i;
let swap = (i,j) => { [heap[i], heap[j]] = [heap[j], heap[i]]; return j}
let heapify = () => {
const max_lvl = Math.floor(Math.log2(k));
for (let lvl = max_lvl - 1; lvl >= 0; lvl--) {
for (let i = Math.pow(2, lvl) - 1; i < Math.pow(2, lvl+1) - 1; i++) {
let cur = i;
let l = left(cur);
let r = right(cur);
// satisfy Min Heap rule
while (heap[cur][1] > heap[l][1] ||
heap[cur][1] > heap[r][1]
) {
if (heap[l][1] < heap[r][1]
) {
cur = swap(cur, l);
} else {
cur = swap(cur, r);
}
l = left(cur);
r = right(cur);
}
}
}
}
for (let i = 0; i < nums.length; i++) {
freq[nums[i]] = (freq[nums[i]] || 0) + 1;
}
for (let val in freq) {
if (heap.length < k) {
heap.push([val, freq[val]]);
continue;
}
heapify();
if (freq[val] > heap[0][1]) {
heap[0] = [val, freq[val]];
}
}
heapify();
for (let i = 0; i < heap.length; i++) {
heap[i] = heap[i][0];
}
return heap;
}
总结
- 我们常说堆栈,其实解题的时候更多的是有意识的用栈、队列,比较少用堆
- JavaScript在构建一个堆的时候,确实不是很便利,但是我们仍需要有堆的思想
- 今天也是有收获的一天