力扣347 前k个高频元素 Java版本

文章目录

  • 题目描述
  • 解题思路
  • 代码


题目描述

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

示例 1:

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

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

提示:

1 <= nums.length <= 105
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。

解题思路

在代码中详细注释了

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //这个题目可以用小根堆来完成,小根堆的实现是树的形式,小根堆中的节点的值都会小于孩子节点
        //把小根堆中的数入队PriorityQueue,也就是排在队头的元素小于排在队尾的元素
        //泛型指定的是int数组,因为需要保存数字和出现的频率,所以需要一个二元数组
        //指定comparator为从小到大排序,并且是根据出现的次数排序
        PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1]-o2[1]);

        int []res = new int[k];//最终答案数组的大小为k
        //统计数字出现的次数,需要用到map
        Map<Integer,Integer> map = new HashMap<>();
        //遍历nums数组,统计各个数字出现的次数,如果map中有这个元素了就次数加一
        for (int i = 0; i < nums.length; i++) {
            //getOrDefault表示如果map中有这个key,就找到这个key对应的value,如果没有这个key则默认value为一个defaultValue,这里是0
            map.put(nums[i],map.getOrDefault(nums[i],0)+1);
        }

        //通过entrySet获取key-value的set集合来遍历map中的值
        for (var x:map.entrySet()){
            int []temp = new int[2];
            temp[0] = x.getKey();//数组的第一位来存储出现的数字
            temp[1] = x.getValue();//数组的第二位来存储数字出现的次数
            pq.offer(temp);

            //队列中小于k个元素就把直接入队,如果大于k个元素就把对头的元素出队,因为用的是小根堆,所以队头元素肯定小于后面的数
            //这一步是因为我们只需要关心出现次数最多的k个数字,不需要关心剩下的数字,所以直接出队就可以了
            if(pq.size()>k){
                pq.poll();
            }
        }
        //最后把K个元素存储到res数组中返回即可
        for (int i = 0; i < k; i++) {
            res[i] = pq.poll()[0];//因为队列中每个元素是存入的int []temp = new int[2];,所以pq.poll()[0]指的是temp[0] = x.getKey();
        }
        return res;
    }
}

你可能感兴趣的:(LeetCode,leetcode,java,算法)