甩一個例題:
考慮到時間複雜度必須優於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小個建立大堆