栈与队列系列⑤ -- 前k个高频元素

题目概述

此题对应力扣的347.前k个高频元素
题目:

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例:

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

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

做题思路

此题使用两种结构:

  • map字典计数
  • 优先级队列排序

为什么使用优先级队列排序,而不是用列表等其他结构?
因为为了保证程序效率,其实我们只用关注前k个元素即可,不用对整个进行排序,而队列可以很好地满足这一点。
如此下来思路就很简单了,具体的做法就是:将数组中的数据用字典计数之后,转化为EntrySet,再将键对值放入优先级队列中,在加的时候同时控制队列的总数不超过k,超过k的弹出去,最后将队列中的元素放入数组中返回即可。

两个注意点

优先级队列的排序问题

因为我们要让前k个最大的留在队列里,所以这个队列要从小到大排序(注意在java的PriorityQueue中最小的元素是排在队头的),满足最小的在队头,最大的在队尾,如此往外弹出溢出k的元素时,才不会把最大的元素弹出去。

Comparator接口的实现

在我们创建优先级队列的时候,因为我们是对Entry的值进行排序,所以我们传入我们自己重写的实现了 Comparator接口的实例,如此才能达到我们的目的。

代码实现

public int[] topKFrequent(int[] nums, int k) {
        //创建一个优先级队列
        Queue<Map.Entry<Integer,Integer>> queue = new PriorityQueue<>((a1,a2) -> a1.getValue() - a2.getValue());
        //创建一个字典计数
        Map<Integer,Integer> map  = new HashMap<>();
        // 开始对数组中的元素计数
        for(int num : nums){
            map.put(num,map.getOrDefault(num,0) + 1);
        }
        // 将键值对放入Set中
        Set<Map.Entry<Integer,Integer>> box = map.entrySet();
        // 将键值对放入优先级队列中(本质小根堆)
        for(Map.Entry<Integer,Integer> entry:box){
            queue.add(entry);
            //只要超过k就把队头的较小值给弹出去
            while (queue.size() > k){
                queue.poll();
            }
        }
        //将队列中的元素拿出来放在数组中返回
        int[] ans = new int[k];
        for(int i = 0;i < k;i++){
            ans[i] = queue.poll().getKey();
        }
        return ans;
    }

代码中的注意点

Java HashMap getOrDefault() 方法

getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。

getOrDefault() 方法的语法为:

hashmap.getOrDefault(Object key, V defaultValue)

参数说明:

  • key - 键
  • defaultValue - 当指定的key并不存在映射关系中,则返回的该默认值

返回值:
返回 key 相映射的的 value,如果给定的 key 在映射关系中找不到,则返回指定的默认值。

lambda表达式

在代码中有一个地方:

Queue<Map.Entry<Integer,Integer>> queue = new PriorityQueue<>((a1,a2) -> a1.getValue() - a2.getValue());

我们在传入Comparator接口的实现类的实例时,可以使用lambda表达式,如此可以使代码更加简洁。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十八岁讨厌编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值