LeetCode 347: 前 K 個高頻元素 Top K Frequent Elements

  • 2019 年 12 月 18 日
  • 筆記

題目:

給定一個非空的整數數組,返回其中出現頻率前 K 高的元素。

Given a non-empty array of integers, return the K most frequent elements.

示例 1:

輸入: nums = [1,1,1,2,2,3], k = 2  輸出: [1,2]  

示例 2:

輸入: nums = [1], k = 1  輸出: [1]  

說明:

  • 你可以假設給定的 k 總是合理的,且 1 ≤ k ≤ 數組中不相同的元素的個數。
  • 你的演算法的時間複雜度必須優於 O(n log n) , n 是數組的大小。

Note:

  • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

解題思路:

這道題大致解題步驟是: 頻率統計 --> 按頻率排序 --> 返回頻率最高的前 K 個元素

注意點:

  • 題目要求時間複雜度優於 O(n log n)

首先頻率統計最優雅的方法應該是藉助哈希映射, key 為元素, value 為頻率. 其時間複雜度為 O(n)

排序演算法很多不再贅述:

重點是返回前 K 個頻率最高的元素, 所以另一種更簡單的方法是直接藉助 堆(優先隊列) 這種數據結構

維護一個 大小為 K 的堆來動態存儲前 K 個頻率最高的元素, 其時間複雜度為 O(n)

程式碼:

Java:

class Solution {      public List<Integer> topKFrequent(int[] nums, int k) {          // 建立哈希映射          HashMap<Integer, Integer> count = new HashMap();          // 頻率統計          for (int n : nums) count.put(n, count.getOrDefault(n, 0) + 1);            // 建立優先隊列, 藉助 Lambda 表達式          PriorityQueue<Integer> heap = new PriorityQueue<Integer>((a, b) -> count.get(a) - count.get(b));          // 也可以藉助 compare 比較函數          // PriorityQueue<Integer> heap = new PriorityQueue<>(new Comparator<Integer>() {          //     @Override          //     public int compare(Integer a, Integer b) {          //         return map.get(a) - map.get(b);          //     }          // });            // 維護一個大小為 k 的已排序的優先隊列          for (int n : count.keySet()) {              heap.add(n);              if (heap.size() > k)                  heap.poll();          }            // 返回結果          List<Integer> top_k = new LinkedList();          while (!heap.isEmpty())              top_k.add(heap.poll());          return top_k;      }  }  

Python:

Python 基礎庫里的 heapq 堆數據結構, 有兩個函數:

  • nlargest
  • nsmallest

例如

heapq.nsmallest(n, nums)  

表示取迭代器 nums 前 n 個最大元素, 該函數還能接受一個 key 關鍵字,以應對複雜的數據結構

結合 collections.Counter() 頻率統計函數, 兩行程式碼即可解決

class Solution:      def topKFrequent(self, nums, k):          """          :type nums: List[int]          :type k: int          :rtype: List[int]          """          count = collections.Counter(nums)          return heapq.nlargest(k, count.keys(), key=count.get)  

注意體會關鍵字參數的作用: key=count.get

Tags: