【桶排序、堆排序】Leetcode --- NO.347 前K个高频元素(Java)

题目描述

在这里插入图片描述

题目分析

  • 这道题就是找出数组内出现频率前几的数组
  • 那么首先要计算数字出现的频率
  • 然后对频率进行排序,但是排序时不可打乱数字和频率的对应关系,找出前几大的数字

解法分析

  • 累计数字出现的频率,这个可以通过map来累计,将数字当作键,将频率当作值
  • 因为最后要返回的是出现频率前几的数字数组,所以频率和数字不可以分开
  • 可以使用桶排序,第几个桶中存储的数据就出现了几次
  • 或者使用堆排序官方题解
  • 这里涉及到 PriorityQueue 类的使用,参考《玩转数据结构之优先队列和堆》以及《PriorityQueue详解》
    在这里插入图片描述

代码

  • 使用桶排序
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
    	// 累计频率
        Map<Integer, Integer> feq = new HashMap<>();
        for(int num:nums){
            feq.put(num, feq.getOrDefault(num, 0)+1);
        }
        List<Integer>[] buckets = new ArrayList[nums.length + 1];
        // 第 i 个桶中存储的数据出现了 i 次 
        for(int key : feq.keySet()){
            int times = feq.get(key);
            if(buckets[times] == null){
                buckets[times] = new ArrayList<>();
            }
            buckets[times].add(key);
        }
        // 从后向前遍历桶,存入结果数组
        List<Integer> res = new ArrayList<>();
        int len = buckets.length - 1;
        for(int i = len;i >= 0 && res.size() < k; i--){
            if(buckets[i] == null){
                continue;
            }
            // 如果这个桶中的数字比结果列表剩余的位置多,那就取一部分即可,因为都是一样的频率
            // 否则就全部放入结果列表中
            if(buckets[i].size() <= k-res.size()){
                res.addAll(buckets[i]);
            } else {
                res.addAll(buckets[i].subList(0, k-res.size()));
            }
        }
        // 将列表转换成数组
        int[] re = new int[k];
        for(int i = 0;i<k;i++){
            re[i] = (Integer)res.toArray()[i];
        }
        return re;
    }
}
  • 官方题解【注意:官方题解返回的是 List 但是实际题目要求返回的是 int[]
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);
    }

    // 初始化堆,频率越小的元素越靠前
    PriorityQueue<Integer> heap =
            new PriorityQueue<Integer>((n1, n2) -> count.get(n1) - count.get(n2));

    // 保持前 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());
    Collections.reverse(top_k);
    return top_k;
  }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/top-k-frequent-elements/solution/qian-k-ge-gao-pin-yuan-su-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值