2022/01/[路飞][LeetCode]347_前 K 个高频元素/index

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

看一百遍美女,美女也不一定是你的。但你刷一百遍算法,知识就是你的了~~

谁能九层台,不用累土起!

题目地址

题目

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

1
2
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

1
2
输入: nums = [1], k = 1
输出: [1]

提示:

  • 1 <= nums.length <= 105
  • k 的取值范围是 [1, 数组中不相同的元素的个数]
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

解题思路

不管看到啥题目,不要慌,我们先想想暴力解如何解

  • 我们用map来记录每个元素出现的次数
  • map转成数组
  • 进行降序排序
  • 截取数组的前k个项
  • 提取元素

解题代码

1
2
3
4
5
6
7
8
var topKFrequent = function(nums, k) {
const map = new Map()
for(let k of nums){
map.set(k,map.has(k)?map.get(k)+1:1)
}
const arr = [...map]
return arr.sort((a,b)=>b[1]-a[1]).slice(0,k).map(v=>v[0])
};

使用小顶堆

先简单的介绍一下堆,堆就是利用完全二叉树的结构来维护的一维数组

堆可以分为大顶堆和小顶堆。

大顶堆:每个结点的值都大于或等于其左右子结点的值。

小顶堆:每个结点的值都小于或等于其左右子结点的值。

如果是排序,求升序用大顶堆,求降序用小顶堆。

一般我们说 topK 问题,就可以用大顶堆或小顶堆来实现,

  • 最大的 K 个:小顶堆
  • 最小的 K 个:大顶堆

在这题中,我们要求的是前k个高频,符合小顶堆的条件

  • 第一步我们还是用map来记录每个元素出现的次数
  • 如果map的长度不够k个就直接返回所有的元素
  • 否则我们遍历map,对小顶堆的长度不够k个时向里面添加数组
  • 当小顶堆的长度达到k个后,我们需要毕竟堆顶的(相对低频)元素的次数是否大于当前遍历到的元素
  • 如果小于当前遍历到的元素的次数,则将堆顶的元素推出,将当前元素入堆
  • 遍历完成后返回所有的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var topKFrequent = function(nums, k) {
const map = new Map()
for(let k of nums){
map.set(k,map.has(k)?map.get(k)+1:1)
}
if(map.size<=k) return [...map.keys()]
const minQueue = new MinPriorityQueue()
map.forEach((val,key)=>{
if(minQueue.size()<k){
minQueue.enqueue(key,val)
}else{
if(minQueue.front().priority<val){
minQueue.dequeue()
minQueue.enqueue(key,val)
}
}
})
return minQueue.toArray().map(v=> v.element)
};

如有任何问题或建议,欢迎留言讨论!

文章作者: Joker
文章链接: https://qytayh.github.io/2022/01/[%E8%B7%AF%E9%A3%9E][LeetCode]347_%E5%89%8D%20K%20%E4%B8%AA%E9%AB%98%E9%A2%91%E5%85%83%E7%B4%A0/index/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Joker's Blog