题目概述
此题对应力扣的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;
}
代码中的注意点
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表达式,如此可以使代码更加简洁。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122328.html