【中等】力扣算法题解析LeetCode347:前 K 个高频元素

关注底部名片达文汐,即可获得本题完整源码

题目来源:LeetCode347.前 K 个高频元素

问题抽象: 给定一个整数数组 nums 和一个整数 k,要求返回数组中 出现频率最高的前 k 个元素,满足以下核心需求:

  1. 频率统计与排序规则

    • 需精确统计数组中 每个元素的出现次数
    • 按频率 从高到低排序,选取频率排名前 k 的元素(频率相同的元素可任意排序)。
  2. 计算约束

    • 时间复杂度 必须优于 O(n log n)n 为数组长度),即禁止全排序;
    • 空间复杂度无严格限制,但需避免冗余存储。
  3. 边界处理

    • 输入数组非空,k 满足 1 ≤ k ≤ 不同元素的数量
    • 当多个元素频率相同时,输出需包含所有频率不低于第 k 名的元素;
    • 特殊值:k = 1 时返回最高频元素,k = 数组元素种类数 时返回所有元素(任意顺序)。

输入:整数数组 nums,整数 k1 ≤ k ≤ 不同元素数量)。
输出:前 k 个高频元素组成的数组(元素顺序不限)。


解题思路

要找出数组中出现频率前 k 高的元素,可以分三步实现:

  1. 频率统计:遍历数组,使用哈希表记录每个元素出现的频率。
  2. 最小堆维护:使用最小堆(优先队列)维护频率最高的 k 个元素。堆中元素按频率升序排序(堆顶频率最小),遍历哈希表时:
    • 当堆大小 < k 时,直接加入元素
    • 当堆大小 = k 时,若当前元素频率 > 堆顶频率,则弹出堆顶后加入新元素
  3. 结果输出:将堆中元素输出为数组(顺序无关,题目不要求有序)

为何用最小堆?
最小堆只需维护 k 个元素,时间复杂度 O(n log k)。最大堆需存所有元素,时间复杂度 O(n log n),效率更低


代码实现(Java版)🔥点击下载源码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        // 1. 统计频率:O(n)
        Map<Integer, Integer> freqMap = new HashMap<>();
        for (int num : nums) {
            freqMap.put(num, freqMap.getOrDefault(num, 0) + 1);
        }

        // 2. 最小堆维护TopK:O(n log k)
        PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> a[1] - b[1]);
        for (Map.Entry<Integer, Integer> entry : freqMap.entrySet()) {
            int num = entry.getKey();
            int freq = entry.getValue();
            // 堆未满时直接加入
            if (minHeap.size() < k) {
                minHeap.offer(new int[]{num, freq});
            } 
            // 堆已满时,仅当当前频率>堆顶频率才替换
            else if (freq > minHeap.peek()[1]) {
                minHeap.poll();     // 弹出堆顶(最小频率)
                minHeap.offer(new int[]{num, freq});
            }
        }

        // 3. 输出结果:O(k)
        int[] result = new int[k];
        for (int i = 0; i < k; i++) {
            result[i] = minHeap.poll()[0];
        }
        return result;
    }
}

代码说明

  1. 频率统计freqMap):

    • 使用 HashMap 存储元素及其出现次数
    • 遍历数组 nums,通过 getOrDefault 快速更新频率
    • 时间复杂度O(n)空间复杂度O(n)
  2. 最小堆维护minHeap):

    • 优先队列按频率升序排序(a[1] - b[1]
    • 遍历哈希表时动态维护堆:
      • 堆大小 < k → 直接加入元素
      • 堆大小 = k → 仅当新元素频率 > 堆顶频率时替换
    • 时间复杂度O(n log k)(最坏情况 n 次堆操作)
  3. 结果输出

    • 从堆中依次取出元素(无需考虑顺序)
    • 时间复杂度O(k)k 次堆弹出操作)

总时间复杂度O(n log k),优于排序解法(O(n log n)) 。总空间复杂度O(n)(哈希表占主导)


提交详情(执行用时、内存消耗)

在这里插入图片描述

我的名片👇👇👇👇👇👇👇👇👇👇👇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达文汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值