[算法基础] 堆相关-数组中前K个高频元素

题目

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

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

示例 2:

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

解题思路

本题和上一题基本类似,都可以使用小顶堆处理,只是上一题第一步是对大小进行排序,构建小顶堆的时候可以借助堆的特性直接得出结果,而本题需要对出现频率进行排序。排序方式很简单,只需要在遍历数组的时候记录频率即可。
我们可以使用map在遍历的过程中记录元素值和出现的频率。然后遍历map取前k个数作构建小顶堆。剩下的步骤就跟上题一致了,从k位开始继续遍历,比较该元素与堆顶元素出现的频率,如果出现的频率高,就直接替换掉堆顶元素,进行堆化,否则不做处理。

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
	var map = new Map(),heap = [,];
	// 记录频率
	nums.map(function(num){
		if(map.has(num)){
			map.set(num,map.get(num) + 1);
		}else{
			map.set(num,1)
		}
	})
	// 如果元素数量小于k
	if(map.size <= k){
		return [...map.keys()]
	}
	// 如果元素数量大于k 则遍历map
	var i = 0; // 记录插入个数
	map.forEach(function(value,key){
		if(i < k){
			heap.push(key);
			// 满足k个之后,原地建堆
			if(i === k -1){
				buildHeap(heap,map,k)
			}
			// 如果k个元素之后的元素出现次数大于堆顶 则替换
		}else if(map.get(heap[1]) < value){
			heap[i] = key
			// 堆化
			heapify(heap,map,k,1)
		}
		i++
	})
	// 删除 堆中第一个占位
	heap.shift()
	return heap
};
// 原地建堆
var buildHeap = function(heap,map,k){
	if(k = 1) return;
	//从最后一个非叶子节点开始,自上而下堆化
	for(var i = Math.floor(k/2);i>=1;i--){
		heapify(heap,map,k,i);
	}
}
//堆化
var heapify = function(heap,map,k,i){
	while(true){
		// 假设i元素最小
		var minindex = i
		if(2*i <= k && map.get(heap[2*i]) < map.get(heap[i])) {
            minIndex = 2*i
        }
        if(2*i+1 <= k && map.get(heap[2*i+1]) < map.get(heap[minIndex])) {
            minIndex = 2*i+1
        }
        if(minIndex !== i) {
            swap(heap, i, minIndex)
            i = minIndex
        } else {
            break
        }
	}
}
// 交换
let swap = (arr, i , j) => {
    let temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值