描述:
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
说明:
你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/top-k-frequent-elements
思路分析:
1、前k个最大:建小根堆,每次弹出根上最小的元素
2、前k个最小:建大根堆,每次弹出根上最大的元素
如何构建小根堆:
PriorityQueue(优先队列),一个基于优先级堆的无界优先级队列。
实际上是一个堆(不指定Comparator时默认为最小堆),通过传入自定义的Comparator函数可以实现大顶堆。
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
@Override
public int compare(Integer i1,Integer i2){
return i2-i1;
}
});
案例: 剑指offer(41) 最小的k个数
PriorityQueue的常用方法有:poll(),offer(Object),size(),peek()等。
插入方法(offer()、poll()、remove() 、add() 方法)时间复杂度为O(log(n)) ;
remove(Object) 和 contains(Object) 时间复杂度为O(n);
检索方法(peek、element 和 size)时间复杂度为常量。
代码实现:
注意:
一定要重写Comparator中的compare函数及其写法!!!
一定要重写Comparato中的comparer函数及其写法!!!
一定要重写Comparator中的compare函数及其写法!!!
class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
// 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i])) {
map.put(nums[i], map.get(nums[i]) + 1);
} else {
map.put(nums[i], 1);
}
}
// 遍历map,用最小堆保存频率最大的k个元素
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return map.get(a) - map.get(b);
}
});
for (Integer key : map.keySet()) {
if (queue.size() < k) {
queue.add(key);
} else if (map.get(key) > map.get(queue.peek())){
queue.remove();
queue.add(key);
}
}
List<Integer> ans = new ArrayList<>();
// 取出最小堆中的元素
while (!queue.isEmpty()) {
ans.add(queue.remove());
}
return ans;
}
}

2429

被折叠的 条评论
为什么被折叠?



