栈与队列系列⑤ -- 前k个高频元素
题目概述
此题对应力扣的347.前k个高频元素
题目:
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
输入: nums = [1], k = 1
输出: [1]
做题思路
此题使用两种结构:
- map字典计数
- 优先级队列排序
为什么使用优先级队列排序,而不是用列表等其他结构?
因为为了保证程序效率,其实我们只用关注前k个元素即可,不用对整个进行排序,而队列可以很好地满足这一点。
如此下来思路就很简单了,具体的做法就是:将数组中的数据用字典计数之后,转化为EntrySet,再将键对值放入优先级队列中,在加的时候同时控制队列的总数不超过k,超过k的弹出去,最后将队列中的元素放入数组中返回即可。
两个注意点
优先级队列的排序问题
因为我们要让前k个最大的留在队列里,所以这个队列要从小到大排序(注意在java的PriorityQueue中最小的元素是排在队头的),满足最小的在队头,最大的在队尾,如此往外弹出溢出k的元素时,才不会把最大的元素弹出去。
Comparator接口的实现
在我们创建优先级队列的时候,因为我们是对Entry的值进行排序,所以我们传入我们自己重写的实现了 Comparator接口的实例,如此才能达到我们的目的。
代码实现
public int[] topKFrequent(int[] nums, int k) {
//创建一个优先级队列
Queue<Map.Entry<Integer,Integer>> queue = new PriorityQueue<>((a1,a2) -> a1.getValue() - a2.getValue());
//创建一个字典计数
Map<Integer,Integer> map = new HashMap<>();
// 开始对数组中的元素计数
for(int num : nums){
map.put(num,map.getOrDefault(num,0) + 1);
}
// 将键值对放入Set中
Set<Map.Entry<Integer,Integer>> box = map.entrySet();
// 将键值对放入优先级队列中(本质小根堆)
for(Map.Entry<Integer,Integer> entry:box){
queue.add(entry);
//只要超过k就把队头的较小值给弹出去
while (queue.size() > k){
queue.poll();
}
}
//将队列中的元素拿出来放在数组中返回
int[] ans = new int[k];
for(int i = 0;i < k;i++){
ans[i] = queue.poll().getKey();
}
return ans;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
代码中的注意点
Java HashMap getOrDefault() 方法
getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。
getOrDefault() 方法的语法为:
hashmap.getOrDefault(Object key, V defaultValue)
参数说明:
- key - 键
- defaultValue - 当指定的key并不存在映射关系中,则返回的该默认值
返回值:
返回 key 相映射的的 value,如果给定的 key 在映射关系中找不到,则返回指定的默认值。
lambda表达式
在代码中有一个地方:
Queue<Map.Entry<Integer,Integer>> queue = new PriorityQueue<>((a1,a2) -> a1.getValue() - a2.getValue());
我们在传入Comparator接口的实现类的实例时,可以使用lambda表达式,如此可以使代码更加简洁。
文章来源: blog.csdn.net,作者:十八岁讨厌编程,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/zyb18507175502/article/details/122381282
- 点赞
- 收藏
- 关注作者
评论(0)