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

导读:本篇文章讲解 栈与队列系列⑤ — 前k个高频元素,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

也许你感觉自己的努力总是徒劳无功,但不必怀疑,你每天都离顶点更进一步。今天的你离顶点还遥遥无期。但你通过今天的努力,积蓄了明天勇攀高峰的力量。加油!

题目概述

此题对应力扣的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表达式,如此可以使代码更加简洁。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122328.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!