先发一张自拍,今天的我长这样~!
正题
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
首先了解一下题意,示例1中 1出现了3次, 2出现了2次 ,3出现了1次,k = 2 ,也就是找出出现次数排名前2的的元素值, 其中 1和2出现次数为第一和第二,所以输出 [1,2]
那么这样一来,这题的核心就是出现次数的排序,然后取前 K 个 值所对应的数据
在之前的文章中有提到计数排序的解析,是通过下标来排序的一种特殊排序方法,顾名思义,即按照顺序进行计数的一种排序手段,其中就可以求的每个元素出现的次数。
上图具体详情具体可参考前文章 计数排序的解析
下面以测试用例:
[4,1,-1,2,-1,2,3]
k=2
为例
先实现一个计数:
var topKFrequent = function(nums, k) {
const min = Math.min(...nums)
const max = Math.max(...nums)
let countList = new Array(max - min + 1).fill(0)
nums.forEach(num => {
countList[num - min] = countList[num - min] + 1
})
console.log({countList})
}
打印结果:
{ countList: [ 2, 0, 1, 2, 1, 1 ] }
这个结果如何去读懂呢?
实际上如果了解过计数排序的应该知道,表示的是
-1 出现过 2次
0 出现过 0次
1 出现过 1次
2 出现过 2次
3 出现过 1次
4 出现过 1次
那么问题来了,得到了这样的数据之后,进行排序,再取前k个元素得到的只能是次数,而并非题目要求的元素的值!(因为 countList 元素表示的是出现次数)
所以在计数的基础上,需要更改数据结构,达到能够找到对应元素值的目的!
修改后:
var topKFrequent = function(nums, k) {
const min = Math.min(...nums)
const max = Math.max(...nums)
let countList = new Array(max - min + 1).fill({val: 0, count: 0})
nums.forEach(num => {
countList[num - min] = {
val : num,
count: countList[num - min].count + 1
}
})
console.log({countList})
};
打印结果
{ countList: [ { val: -1, count: 2 }, { val: 0, count: 0 },
{ val: 1, count: 1 }, { val: 2, count: 2 },
{ val: 3, count: 1 }, { val: 4, count: 1 } ] }
这样数据结构就非常的清晰了!接下来就是筛选操作的体力活,就不做过多介绍, show you my code !
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/ // 3 2 5 7. 2-0 3-1
var topKFrequent = function(nums, k) {
const min = Math.min(...nums)
const max = Math.max(...nums)
let countList = new Array(max - min + 1).fill({val: 0, count: 0})
nums.forEach(num => {
countList[num - min] = {
val : num,
count: countList[num - min].count + 1
}
})
countList = countList.sort((a,b) => {return b.count - a.count})
let index = 0
const res = []
while(index < k) {
res.push(countList[index].val)
index++
}
return res
};