题目描述:
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
思路和知识:没有思路:只能想到用map统计出现的频率
现在做题太追求上去就考虑时间复杂度了,需要先捋清楚思路,能做出来再考虑优化,降低时间复杂度!
1)优先级队列PriorityQueue
第一次见,内部实现是使用完全二叉树的堆形式,有大顶堆(节点值大于左右孩子节点)和小顶堆两种形式(节点值小于左右孩子节点);poll时,是从根节点开始 弹出!
创建 优先级队列时,需要在构造函数里实现 一个比较器,如下形式:
函数式接口:
PriorityQueue<Map.Entry<Integer, Integer>> queue =
new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue());
匿名类的形式:
PriorityQueue<Map.Entry<Integer,Integer>> queue =
new PriorityQueue<>(new Comparator<Map.Entry<Integer,Integer>>(){
public int compare(Map.Entry<Integer,Integer> e1,Map.Entry<Integer,Integer> e2){
return e1.getValue() - e2.getValue();
}
});
2)Map的使用,使用HashMap
①有map.getOrDefault()方法,put方法
②Map的遍历使用 EntrySet:Map.Entry<> map.entrySet()
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
queue.offer(entry);
if(queue.size() > k){
//如果已经大于需要的k了,就先弹出小的,再往里面放
queue.poll();
}
}
代码:
1)优先级队列 + Map统计频率
class Solution {
public int[] topKFrequent(int[] nums, int k) {
//不嵌套for循环,就不会乘?
//用Map统计频率
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i < nums.length;i++){
map.put(nums[i],map.getOrDefault(nums[i],0) + 1);//统计每个字符出现的频率
}
//Set和Map的遍历可以使用迭代器,Map中可以使用 Entry键值对
//优先权队列中,构造函数的 形参需要是一个比较器,comparator
//按照创建的大顶堆和小顶堆的不同,来构建 比较器
PriorityQueue<Map.Entry<Integer,Integer>> queue = new PriorityQueue<>(new Comparator<Map.Entry<Integer,Integer>>(){
public int compare(Map.Entry<Integer,Integer> e1,Map.Entry<Integer,Integer> e2){
return e1.getValue() - e2.getValue();
}
});
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
queue.offer(entry);
if(queue.size() > k){
//如果已经大于需要的k了,就先弹出小的,再往里面放
queue.poll();
}
}
//已经添加完成
//倒序输出
int[] res = new int[k];
for(int i = k -1;i >= 0;i--){
res[i] = queue.poll().getKey();
}
return res;
}
}
2)答案还有 排序算法!