一般TopK問題建議的解法

甩一個例題:
在這裏插入圖片描述
考慮到時間複雜度必須優於nlogn ,那麼就不能用暴力搜索法

首先利用map統計個元素出現的次數:

Map<Integer, Integer> map = new HashMap<>();
for (int x: nums) {
    map.put(x, map.getOrDefault(x, 0) + 1);
}

此時有兩種處理思路:

  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個
  1. 利用優先級隊列(建立小堆):
    先將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小個建立大堆

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章