当前位置:   article > 正文

LeetCode 347: 前 K 个高频元素 Top K Frequent Elements

c++给定一个非空的整数数组a,返回其中出现频率前 k 高的元素。——博客园

题目:

给定一个非空的整数数组,返回其中出现频率前 K 高的元素。

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

示例 1:

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

示例 2:

  1. 输入: nums = [1], k = 1
  2. 输出: [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:

  1. class Solution {
  2.     public List<Integer> topKFrequent(int[] nums, int k) {
  3.         // 建立哈希映射
  4.         HashMap<Integer, Integer> count = new HashMap();
  5.         // 频率统计
  6.         for (int n : nums) count.put(n, count.getOrDefault(n, 0) + 1);
  7.         // 建立优先队列, 借助 Lambda 表达式
  8.         PriorityQueue<Integer> heap = new PriorityQueue<Integer>((a, b) -> count.get(a) - count.get(b));
  9.         // 也可以借助 compare 比较函数
  10.         // PriorityQueue<Integer> heap = new PriorityQueue<>(new Comparator<Integer>() {
  11.         //     @Override
  12.         //     public int compare(Integer a, Integer b) {
  13.         //         return map.get(a) - map.get(b);
  14.         //     }
  15.         // });
  16.         // 维护一个大小为 k 的已排序的优先队列
  17.         for (int n : count.keySet()) {
  18.             heap.add(n);
  19.             if (heap.size() > k)
  20.                 heap.poll();
  21.         }
  22.         // 返回结果
  23.         List<Integer> top_k = new LinkedList();
  24.         while (!heap.isEmpty())
  25.             top_k.add(heap.poll());
  26.         return top_k;
  27.     }
  28. }

Python:

Python 基础库里的 heapq 堆数据结构, 有两个函数:

  • nlargest

  • nsmallest

例如

heapq.nsmallest(n, nums)

表示取迭代器 nums 前 n 个最大元素, 该函数还能接受一个 key 关键字,以应对复杂的数据结构

结合 collections.Counter() 频率统计函数, 两行代码即可解决

  1. class Solution:
  2.     def topKFrequent(self, nums, k):
  3.         """
  4.         :type nums: List[int]
  5.         :type k: int
  6.         :rtype: List[int]
  7.         """ 
  8.         count = collections.Counter(nums)   
  9.         return heapq.nlargest(k, count.keys(), key=count.get) 

注意体会关键字参数的作用: key=count.get

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/72757
推荐阅读
相关标签
  

闽ICP备14008679号