持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums = [1], k = 1 输出: [1]
思路分析
获取前k个高频元素,从题目中来看,我们需要找到出现频率最多的前k个元素,我们可以将每个元素的出现次数收集起来作为一个新的数组或者对象,然后从这个数组中获取出现频率前k个元素,这样我们可以使用堆排序的方式来获取结果,只需要获取最上层的元素而不需要关心整体元素的排序情况,只不过该题比较绕,不能直接将数组继续堆排序,需要将数组元素的出现次数保存到字典中,然后我们将字典中的元素进行一个堆排序,并获取前k个元素
首先我们将数组依次插入到一个字典类中,在插入的时候先判断是否字典中是否已经有值,如果已有值就加1,没有就将其设为1。然后遍历字典中的值将其插入堆中,构建一个最大堆,新插入元素会与父元素进行比较如果大于父元素则交换位置并继续进行比较直到到达堆顶或者比父元素小,在字典中 的值都插入到堆中之后,就可以开始获取前k个高频元素了,将堆中最上层的元素收集到数组中k-1次,就能得到结果了
var topKFrequent = function(nums, k) {
let heap = []
let heapObj = {}
let arr = []
//重新组建数组
nums.forEach(item=>{
heapObj[item] = heapObj[item]?heapObj[item]+1:1
})
for(let i in heapObj){
insert({key:i,val:heapObj[i]})
}
//插入堆
function insert(val){
heap.push(val)
shiftUP(heap.length-1)
}
//上移操作
function shiftUP(index){
if(index===0)return
let parentIndex = Math.floor((index-1)/2)
if(heap[index].val>heap[parentIndex].val){
let tmp = heap[parentIndex]
heap[parentIndex] = heap[index]
heap[index] = tmp
shiftUP(parentIndex)
}
}
//下移操作
function shiftDown(index){
let leftIndex = index*2+1
if(!heap[leftIndex])return
let rightIndex = index*2+2
if(heap[index].val<heap[leftIndex].val){
let tmp = heap[leftIndex]
heap[leftIndex] = heap[index]
heap[index] = tmp
shiftDown(leftIndex)
}
if(!heap[rightIndex])return
if(heap[index].val<heap[rightIndex].val){
let tmp = heap[rightIndex]
heap[rightIndex] = heap[index]
heap[index] = tmp
shiftDown(rightIndex)
}
}
//删除
function pop(){
heap[0] = heap.pop()
shiftDown(0)
}
for(let i = 0; i < k; i++){
arr.push(heap[0].key)
pop()
}
return arr
};