题目
方法:堆
分析
1.用HashMap记录数字和它们出现的次序。
2.创建一个小顶的,容量为k的优先队列。将map中的元素依次加入优先队列。
如果优先队列大小<k,直接加入;
如果优先队列大小>=k,比较堆顶.value和当前.value。如果堆顶.value小,则删除堆顶,再插入当前元素。否则,舍弃当前元素。
3.将优先队列k个元素加入结果返回。
代码
class Solution {
public int[] topKFrequent(int[] nums, int k) {
if(nums==null||nums.length==0||k==0)
return new int[0];
HashMap<Integer,Integer> map=new HashMap<>();
for(int n:nums){
if(!map.containsKey(n)){
map.put(n,1);
}
else{
map.put(n,1+map.get(n));
}
}
PriorityQueue<Map.Entry<Integer, Integer>> queue=new PriorityQueue<Map.Entry<Integer, Integer>>(map.size(),new Comparator< Map.Entry<Integer, Integer> >(){
public int compare(Map.Entry<Integer, Integer> i1,Map.Entry<Integer, Integer> i2){
return i1.getValue()-i2.getValue();
}
});
for(Map.Entry<Integer, Integer> entry : map.entrySet()){
if(queue.size()<k){
queue.add(entry);
}
else{
if(queue.peek().getValue()<entry.getValue()){
queue.poll();
queue.add(entry);
}
}
}
int[] res=new int[k];
for(int i=0;i<k;i++){
res[i]=queue.poll().getKey();
}
return res;
}
}
复杂度
时间复杂度:O(Nlogk),其中 N 为数组的长度。我们首先遍历原数组,并使用哈希表记录出现次数,每个元素需要 O(1) 的时间,共需 O(N)的时间。随后,我们遍历「出现次数数组」,由于堆的大小至多为 k,因此每次堆操作需要 O(logk) 的时间,共需 O(Nlogk) 的时间。二者之和为O(Nlogk)。
空间复杂度:O(N))。哈希表的大小为O(N),而堆的大小为 O(k),共计为O(N)。