leetcode【栈与队列—中等】 347.前 K 个高频元素

简介: leetcode【栈与队列—中等】 347.前 K 个高频元素

题目


题目来源leetcode


leetcode地址:347. 前 K 个高频元素,难度:中等。


题目描述(摘自leetcode):


给你一个整数数组 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 个高频元素的集合是唯一的


本地调试代码:


class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        ...
    }
    public static void main(String[] args) {
        int[] nums = new int[]{1,1,1,2,2,3};
        System.out.println(Arrays.toString(new Solution().topKFrequent(nums,2)));
    }
}



题解


NO1:哈希表+优先队列


思路: 先使用哈希表来进行统计对应值的频率,之后创建一个优先队列设置一个从小到大排序的比较器,每次插入一组key、value后,判断当前的容量是否>k个,若是大于了直接将队头的出队(在队列里频率最小的),最终遍历取出队列中的k组数据即可。


代码:


public int[] topKFrequent(int[] nums, int k) {
    //使用map来进行统计指定指定数的频率,key为num,value为频率
    Map<Integer,Integer> map = new HashMap<>();
    for (int num : nums) {
        map.put(num,map.getOrDefault(num,0)+1);
    }
    Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
    //创建优先队列,传入Comparator匿名接口类,插入队列的元素从小到达排列
    PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1,o2)->o1.getValue()-o2.getValue());
    for (Map.Entry<Integer, Integer> entry : entries) {
        queue.offer(entry);
        if(queue.size() > k){  //一旦队列中的数量大于k,直接将频率最小的出队(队头)
            queue.poll();
        }
    }
    //最终取出对应的最大k值
    int[] maxNums = new int[k];
    for (int i = k-1; i >=0 ; i--) {
        maxNums[i] = queue.poll().getKey();
    }
    return maxNums;
}


NO2:排序遍历+优先队列

思路:首先进行从小到大排序,之后对整个数组进行遍历,以[i]!=[i-1]来作为存储到队列的依据,队列按照从大到小排序,每次入队后判断是否>k个,若是大于出队。最终遍历k个即可获取到前k个高频元素。


代码:


public int[] topKFrequent(int[] nums, int k) {
    Arrays.sort(nums);
    //优先队列,按照频率从小到大排列(Comparator返回值为负数就从小到大排列,若是正数从大到小)
    PriorityQueue<int[]> queue = new PriorityQueue<int[]>((o1, o2) -> o1[1] - o2[1]);
    //对数组进行遍历操作
    int i = 1;
    int j = 1;
    for (; i < nums.length; i++) {
        if (nums[i] == nums[i - 1]) {
            j++;
        } else {
            queue.offer(new int[]{nums[i - 1], j});
            if (queue.size() > k) {  //一旦大于原本k个数量就进行移除
                queue.poll();
            }
            j = 1;
        }
    }
    queue.offer(new int[]{nums[i - 1], j});
    if (queue.size() > k) {
        queue.poll();
    }
    //从队列中取出k个
    int[] maxNums = new int[k];
    for (int l = 0; l < k; l++) {
        maxNums[l] = queue.poll()[0];
    }
    return maxNums;
}


相关文章
|
2月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
37 1
|
2月前
【LeetCode 27】347.前k个高频元素
【LeetCode 27】347.前k个高频元素
36 0
|
2月前
【LeetCode 24】225.用队列实现栈
【LeetCode 24】225.用队列实现栈
12 0
|
2月前
|
算法
【LeetCode 23】232.用栈实现队列
【LeetCode 23】232.用栈实现队列
24 0
|
2月前
【LeetCode 06】203.移除链表元素
【LeetCode 06】203.移除链表元素
33 0
|
2月前
【LeetCode-每日一题】移除元素
【LeetCode-每日一题】移除元素
32 0
|
4月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
4月前
|
算法 索引
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
这篇文章介绍了LeetCode第34题"在排序数组中查找元素的第一个和最后一个位置"的解题方法,通过使用双指针法从数组两端向中间同时查找目标值,有效地找到了目标值的首次和最后一次出现的索引位置。
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
|
4月前
|
算法
LeetCode第27题移除元素
这篇文章介绍了LeetCode第27题"移除元素"的解题方法,通过使用双指针技巧,有效移除数组中特定值的元素并返回新数组的长度。
|
3月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行