前 K 個高頻元素問題

前 K 個高頻元素問題

作者:Grey

原文地址: 前 K 個高頻元素問題

題目描述

LeetCode 347. Top K Frequent Elements

思路

第一步,針對數組元素封裝一個數據結構

public class Node {
    int v;
    int t;
    public Node(int value, int times) {
        v = value;
        t = times;
    }
}

其中v表示數組元素,t表示數組元素出現的次數。

第二步,使用哈希表把每個元素的詞頻先存一下。其中key是數組元素,valueNode類型,封裝了數組元素和次數。

        Map<Integer, Node> freqMap = new HashMap<>();
        for (int n : arr) {
            if (freqMap.containsKey(n)) {
                // 存在就把詞頻加一
                freqMap.get(n).t++;
            } else {
                // 不存在就新建一個詞頻
                freqMap.put(n, new Node(n, 1));
            }
        }

第三步,使用一個小根堆,按詞頻從小到大。我們需要將這個小根堆維持在K個高頻元素。具體做法如下

如果堆未超過K個元素,可以入堆;

如果堆已經到了K個元素了,就看堆頂的元素出現的次數是否比即將要遍歷的元素出現的次數少,如果堆頂元素出現的次數比即將要遍歷的元素少,

說明即將遍歷的元素比堆頂元素更高頻,可以替換掉堆頂元素,將其入堆;

如果堆已經超過K個元素了,那麼彈出元素,讓堆始終保持在K個元素。

第四步,彈出堆中所有元素,即爲前K個高頻元素。

完整代碼如下:

    public static class Node {
        // 值
        public int v;
        // 次數
        public int t;

        public Node(int value, int times) {
            v = value;
            t = times;
        }
    }

    public static int[] topKFrequent(int[] arr, int k) {
        if (arr == null || arr.length == 0 || arr.length < k) {
            return null;
        }
        Map<Integer, Node> freqMap = new HashMap<>();
        for (int n : arr) {
            if (freqMap.containsKey(n)) {
                freqMap.get(n).t++;
            } else {
                freqMap.put(n, new Node(n, 1));
            }
        }
        // 字符種類沒有k個,無法得到結果
        if (freqMap.size() < k) {
            return null;
        }
        int[] ans = new int[k];
        PriorityQueue<Node> topK = new PriorityQueue<>(k, Comparator.comparingInt(o -> o.t));
        for (Map.Entry<Integer, Node> entry : freqMap.entrySet()) {
            if (topK.size() <= k || topK.peek().t < entry.getValue().t) {
                topK.offer(entry.getValue());
            }
            if (topK.size() > k) {
                topK.poll();
            }
        }
        int i = 0;
        while (!topK.isEmpty()) {
            ans[i++] = topK.poll().v;
        }
        return ans;
    }

更多

算法和數據結構筆記

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