甩一个例题:
考虑到时间复杂度必须优于nlogn ,那么就不能用暴力搜索法
首先利用map统计个元素出现的次数:
Map<Integer, Integer> map = new HashMap<>();
for (int x: nums) {
map.put(x, map.getOrDefault(x, 0) + 1);
}
此时有两种处理思路:
- 利用sort();
先将map中的key值存进List中
再对其进行排序(需要自己定义比较器):
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return map.get(o1) - map.get(o2);
}
});
最后输出已排序集合的前K个
- 利用优先级队列(建立小堆):
先将map中的key值存入堆中,并且保证堆中只有k个元素
for (int x: map.keySet()) {
heap.offer(x);
if (heap.size() > k) {
heap.poll();
}
}
再将堆中的元素复制进list之中
反转list(小堆的结构决定)
返回list
附代码:
import java.util.*;
public class TopKFrequentNum {
public static List<Integer> topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int x: nums) {
map.put(x, map.getOrDefault(x, 0) + 1);
}
PriorityQueue<Integer> heap = new PriorityQueue<>(
new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return map.get(o1) - map.get(o2);
}
}
);
for (int x: map.keySet()) {
heap.offer(x);
if (heap.size() > k) {
heap.poll();
}
}
List<Integer> list = new ArrayList<>(heap);
Collections.reverse(list);
return list;
}
public static void main(String[] args) {
int[] nums = {4,1,-1,2,-1,2,3};
System.out.println(topKFrequent(nums, 2).toString());
}
}
总结:
找前K大个建立小堆
找前K小个建立大堆