持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
前言
今天继续练习栈与队列方面的算法题,做到leetcode 347.前K个高频元素,通过这道题又学习了优先队列的概念,分享并记录一下。
题目
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
思考
对于题目要求找出出现频率前k高的元素,我们需要计算出元素出现的频率,很容易想到用Map的方式统计:
countMap.set(num, (countMap.get(num) || 0) + 1)
有很多相似的题也可以通过Map的方式解决。
但是这不是这道题的核心点,核心是要把计算出的频率排序并输出k个高频元素。通过查找资料以及看了一些大佬的题解,我发现了一个新的知识——优先级队列,那么什么是优先级队列呢?
优先级队列
优先级队列本质上是一个堆结构,但由于其从对头取元素,从队尾添加元素,所以看起来像是一个队列。优先级队列通过堆的方式排序。学过数据结构的人知道,堆就是一颗完全二叉树,大顶堆根节点大于其左右孩子的值,小顶堆根节点小于其左右孩子的值。
那么我们就可以采用小顶堆,每次将最小的元素弹出,最终留下最大的k个元素,就是最终的结果。
注意:js与ts没有最小堆的数据结构,所以直接对整个数组进行排序,取前k个元素
代码实现
function topKFrequent(nums: number[], k: number): number[] {
const countMap: Map<number, number> = new Map();
for (let num of nums) {
countMap.set(num, (countMap.get(num) || 0) + 1);
}
// tS没有最小堆的数据结构,所以直接对整个数组进行排序,取前k个元素
return [...countMap.entries()]
.sort((a, b) => b[1] - a[1])
.slice(0, k)
.map(i => i[0]);
};