leetcode 347. Top K Frequent Elements(前k个频率最高的元素)

本文介绍了一种高效查找数组中前K个频率最高元素的算法。通过使用两个数组,分别统计数字出现次数及对应数字,实现了从高到低的频率排序。最终返回所需的K个最频繁元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

给出一个数组,找出前k个频率最高的元素,k是有效的

思路:
可以用一个hashMap统计每个数字出现的次数,
但是简单点的写法,不用HashMap,用数组cnt代替,数组下标表示数字,为了减小数组的长度,可以提前看数字的范围min~max,数组长度取max-min+1即可。

现在只找到了每个数字出现的次数,并不能按照次数从大到小排列,
因此还需要一个数组来做这件事情,按次数从大到小排列,还要能找到对应的数字。
这就需要数组的下标是次数,这样从右到左遍历就相当于按次数从大到小。
只需要在每个下标处保存对应的数字即可。

所以再用一个list数组,数组下标对应数字出现的次数,
这样,从右到左遍历数组 就相当于 从大到小遍历次数。
每个频率的list装入出现这个次数的数字。

i+min就是出现这个频率的数字,注意一定要+min,因为刚刚cnt的下标,也就是nums中的数字,从min~max映射到0~max-min+1了,也就是全减掉了min,现在要加回来。

再来理一遍,有两个数组,第一个,统计每个数字出现的次数。这时数组下标是数字,数组元素是数字出现的次数。
第2个,元素是list的数组,统计每个出现次数都有哪些数字(第一个的反向操作),相当于把第一个数组的元素当作下标,第一个数组的下标装入list.

最后,从右到左遍历第2个数组,取出list中的数字,直到取出k个为止。

    public int[] topKFrequent(int[] nums, int k) {
        if(nums.length == 1) return nums;
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
        int maxCnt = 0;
        int[] res = new int[k];

        for(int num : nums) {
            min = Math.min(min, num);
            max = Math.max(max, num);
        }

        //统计每个数字出现的次数
        int[] cnt = new int[max-min+1];
        for(int num : nums) {
            cnt[num-min]++;
            maxCnt = Math.max(maxCnt, cnt[num-min]); //最大次数
        }

        //统计每个次数对应的数字
        List<Integer>[] cntNum = new ArrayList[maxCnt+1]; 
        for(int i = 0; i < cnt.length; i++) {
            if(cnt[i] == 0) continue;
            if(cntNum[cnt[i]] == null) cntNum[cnt[i]] = new ArrayList<Integer>();
            cntNum[cnt[i]].add(i+min);
        }

        //按频率大小装入数字
        for(int i = cntNum.length-1; i >= 0; i--) {
            if(cntNum[i] == null) continue;
            for(Integer num : cntNum[i]) {                
                res[--k] = num;   
                if(k <= 0) return res;            
            }
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蓝羽飞鸟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值