给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
**输入:**nums = [1,1,1,2,2,3], k = 2
输出:[1,2]
示例 2:
**输入:**nums = [1], k = 1
输出:[1]
示例 3:
**输入:**nums = [1,2,1,2,1,2,3,1,3,2], k = 2
输出:[1,2]
一、最小堆
思路:
这是一个Top K 问题 ,优先想到的就是使用最小堆/最大堆 ,使用优先级队列 PriorityQueue实现,PriorityQueue 虽然继承队列接口,但实际底层封装的是树结构,所以它满足堆的所有特性,它就是堆的具体实现。
我们首先创建一个哈希map,key存数组元素,value 存出现的频率,使用map辅助,一是能记录频率,二是能去重。再创建一个最小堆,用map 中的value 来排序。在遍历map 的键数组的过程中,让堆的大小为k,超出k 时移除堆顶元素,最后得到的堆就是包含前k 个高频元素的堆了。
时间复杂度O(n log k),因为堆是树结构,所以插入删除都是log k,当数组元素都不同时遍历耗时n
代码:
java
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 使用map辅助,一是能记录频率,二是能去重
Map<Integer, Integer> frequentMap = new HashMap<>();
for(int num : nums){
frequentMap.put(num, frequentMap.getOrDefault(num, 0) + 1);
}
PriorityQueue<Integer> minHeap = new PriorityQueue<>(
(a, b) -> frequentMap.get(a) - frequentMap.get(b)
);
// map的keySet帮助去重了
for(int num : frequentMap.keySet()){
minHeap.offer(num);
if(minHeap.size() > k){
minHeap.poll();
}
}
int[] reslut = new int[k];
for(int i = 0; i < k; i++){
reslut[i] = minHeap.poll();
}
return reslut;
}
}