参考知识:优先队列 (通过最大堆实现的)
优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素)。这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序(natural ordering),也可以通过构造时传入的比较器(Comparator)。
Java中PriorityQueue实现了Queue接口,不允许放入null
元素;其通过最小堆实现
题目描述:
给定一个非空的整数数组,返回其中出现频率前 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 是数组的大小
解答:
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;
import java.util.PriorityQueue;
class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
TreeMap<Integer,Integer> map=new TreeMap<>();
//将数组中的值放入map集合中,并统计其出现频次
for(int num:nums){
if(!map.containsKey(num)) {
map.put(num,1);
}
map.put(num, map.get(num)+1);
}
//java中的优先队列(小顶堆),传入比较器
PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return map.get(o1)-map.get(o2);
}
});
//循环遍历map集合,将前K高的元素放入优先队列中
for(int key:map.keySet()) {
if(queue.size()<k) {
queue.add(key);
}else if(map.get(key)>map.get(queue.peek())){
queue.remove();
queue.add(key);
}
}
LinkedList<Integer> res=new LinkedList<>();
//将优先队列转为list输出
while(!queue.isEmpty()) {
res.add(queue.remove());
}
return res;
}
}