这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战
大家好今天给大家分享下一道 LeetCode 中等难度 的题目[剑指 Offer II 060. 出现频率最高的 k 个数字]
题目
给定一个整数数组
nums和一个整数k,请返回其中出现频率前k高的元素。可以按 任意顺序 返回答案。
示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums = [1], k = 1 输出: [1]
分析
1.整数数组
2.可能有重复的元素
3.k为整数小于数组长度
4.返回频率前k高的数组
解法
1.hashmap+sort
2.maxheap
*/
解法一:hashmap+sort
思路
1.创建一个对象来存储频次
2.然后给频次排序
3.输出前k个元素
*/
var topKFrequent = function (nums, k) {
const map = {};
for (const item of nums) {
map[item] ? (map[item] = map[item] + 1) : (map[item] = 1);
}
const arr = [];
Object.keys(map).forEach((key) => {
arr.push({ key: key, value: map[key] });
});
// 排序单调减
arr.sort((a, b) => {
return a.value - b.value;
});
const res = [];
for (let i = 0; i < arr.length; i++) {
if (i >= arr.length - k) {
res.push(arr[i].key);
}
}
return res;
};
/* 复杂度
时间 O(nlogn)
空间 O(nlogn)
*/
解法二:maxheap
思路
1.自定义maxHeap类,保持根元素最大
2.使用堆来取前k个根元素
*/
function swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
class MaxHeapObj {
constructor(arr) {
this.array = [];
// 判断必须是数组
if (Array.isArray(arr)) {
for (const item of arr) {
this.insert(item);
}
}
}
insert(item) {
this.array.push(item);
let index = this.array.length - 1;
// 当插入的时候保持父级大于子级
while (index) {
const parentIndex = Math.floor((index - 1) / 2);
if (this.array[index].value < this.array[parentIndex].value) {
break;
}
swap(this.array, index, parentIndex);
index = parentIndex;
}
}
poll() {
if (!this.array.length) return null;
swap(this.array, 0, this.array.length - 1);
const res = this.array.pop();
// 删除最大值的时候一直向下轮换保持父级大于子级元素
let index = 0;
let compareIndex = index * 2 + 1;
while (compareIndex < this.array.length) {
const right = index * 2 + 2;
if (
right < this.array.length &&
this.array[right].value > this.array[compareIndex].value
) {
compareIndex = right;
}
if (this.array[compareIndex].value <= this.array[index].value) {
break;
}
swap(this.array, index, compareIndex);
index = compareIndex;
compareIndex = index * 2 + 1;
}
return res;
}
}
var topKFrequent = function (nums, k) {
if (k === 0 || nums.length === 0) {
return [];
}
// 使用map统计频次
const map = {};
for (const item of nums) {
map[item] ? (map[item] = map[item] + 1) : (map[item] = 1);
}
// 使用arr来存储频次的对象数组
const arr = [];
Object.keys(map).forEach((key) => {
arr.push({ key: key, value: map[key] });
});
// 把数组放入maxHeap中保持根本最大
const maxHeapObj = new MaxHeapObj(arr);
// 取出最大的前K个最大频次的元素
const res = [];
for (let i = 0; i < k; i++) {
res.push(maxHeapObj.poll());
}
// 因为返回的是对象 所以需要利用array.map 处理下
return res.map((item) => item.value);
};
/* 复杂度
时间 O(nlogn)
空间 O(nlogn)
*/
总结
这道题考察的也是maxHeap求解前k个最高频次是元素,只是需要稍微改造下就maxHeap类就OK,还有就是利用sort+hashMap来求解(内容和这道题基本相似 juejin.cn/post/700073…
大家可以看看我分享的一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能够帮到大家,我会尽量保持每天晚上更新,如果喜欢的麻烦帮我点个赞,十分感谢
大家如果对“TS”感兴趣的可以看看我的专栏 (TypeScript常用知识),感谢大家的支持
文章内容目的在于学习讨论与分享学习算法过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com