347. 前 K 个高频元素
常规思路 哈希
比如:nums = [1,1,1,2,2,2,3,3,8,8], k = 2
通过哈希表统计数组中各个元素出现的次数;nums哈希表如下
| 元素 | 1 | 2 | 3 | 8 |
|---|---|---|---|---|
| 元素出现次数 | 3 | 3 | 2 | 2 |
上述表格中,只需要将元素出现次数降序排列获取前K个即可得到前K个高频数;
根据上述思路编辑代码如下:
const topKFrequent = (nums, k) => {
//哈希表,保存数组元素出现次数
const map = {}
nums.forEach((n) => {
map[n] = (map[n] || 0) + 1
})
const list = []
//遍历数据,将元素,和原元素出现次数放在list中
Object.keys(map).forEach((k) => {
list.push([Number(k),map[k]])
})
// list排序
list.sort((a,b)=>{
return b[1] - a[1]
})
//截取前k个元素
const result = list.slice(0,k)
//返回答案
return result.map(v=>v[0])
}
代码AC木有问题,但是使用sort排序,时间复杂度是O(nlogn)级别;所以还要优化一下
空间换时间
上述用到哈希表;顺着这个思路,可以再用一个桶,将元素和元素出现的次数按照表格中的规律放入桶中;
| 出现次数 | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 元素 | 0 | 0 | 3,8 | 1,2 |
如果nums = [4,5,5,9,9,9,9,7]
| 出现次数 | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| 元素 | 0 | 4,7 | 5 | 0 | 9 |
解释上述表格:
出现3次的数据有1、2;
出现2次的数据有3、8
出现1、0次的数据没有
假设结果数组为result 从右到左遍历这个桶,如果桶中某个位置有元素,将元素放在result
当result.length === k;输出答案
根据上述思路编辑代码如下:
const topKFrequent = (nums, k) => {
const map = {}
nums.forEach((n) => {
map[n] = (map[n] || 0) + 1
})
// 先统计出现的次数,如果数据量少于k返回
if (Object.keys(map).length <= k) {
return Object.keys(map)
}
// 数据量超过k呢?
// 找个桶,桶最长为k;
const list = []
//遍历数据
Object.keys(map).forEach((k) => {
const idx = map[k]
list[idx] = (list[idx] || []).concat(k)
})
const result = []
for (let i = list.length - 1; i >= 0; i--) {
if (result.length === k) return result.map(Number)
if (list[i]) {
result.push(...list[i])
}
}
//console.log('list', list)
}