力扣 - 347. 前 K 個高頻元素
阿新 • • 發佈:2020-11-24
目錄
題目
思路1(雜湊表與排序)
- 先用雜湊表記錄所有的值出現的次數
- 然後將按照出現的次數進行從高到低排序
- 最後取前 k 個就是答案了
程式碼
class Solution { public int[] topKFrequent(int[] nums, int k) { HashMap<Integer, Integer> hashtable = new HashMap<>(); // 統計每個次數出現的次數 for (int num : nums) { hashtable.put(num, hashtable.getOrDefault(num, 0) + 1); } // 排序 List<Map.Entry<Integer, Integer>> list = new ArrayList<>(hashtable.entrySet()); list.sort(new Comparator<Map.Entry<Integer, Integer>>() { @Override public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) { return o2.getValue().compareTo(o1.getValue()); } }); // 獲取前k高的結果 int[] res = new int[k]; for (int i = 0; i < k; i++) { res[i] = list.get(i).getKey(); } return res; } }
複雜度分析
- 時間複雜度:\(O(NlogN)\),其中 N 為陣列長度,遍歷一遍花的時間是N,但是由於排序的時間複雜度是NlogN,所以總的時間複雜度為NlogN
- 空間複雜度:\(O(N)\),其中 N 為陣列長度
思路2(建堆)
- 也是先用雜湊表統計出現的次數
- 然後利用小頂堆獲取前k高的元素,堆操作的時間複雜度為logk,所以總的就是Nlogk
程式碼
class Solution { public int[] topKFrequent(int[] nums, int k) { // 用雜湊表儲存出現次數 Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>(); for (int num : nums) { hashtable.put(num, hashtable.getOrDefault(num, 0) + 1); } // 使用優先佇列 PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { return o1[1] - o2[1]; } }); // 小頂堆,容量只為k,儲存前n大的元素 for (Map.Entry<Integer, Integer> entry : hashtable.entrySet()) { int element = entry.getKey(); int count = entry.getValue(); if (queue.size() == k) { // 保證佇列儲存的前k個元素出現頻率都是最多的 if (queue.peek()[1] < count) { queue.poll(); queue.offer(new int[]{element, count}); } } else { queue.offer(new int[]{element, count}); } } // 將優先佇列元素出隊轉換為結果 int[] res = new int[k]; for (int i = 0; i < k; i++) { res[i] = queue.poll()[0]; } return res; } }
複雜度分析
- 時間複雜度:\(O(Nlogk)\),其中 N 為陣列長度,由於堆的大小至多為 k,因此每次堆操作需要 O(logk) 的時間,共需 O(Nlogk) 的時間
- 空間複雜度:\(O(N)\),其中 N 為陣列長度