【算法系列-栈与队列】队列的应用(前k高频元素 + 滑动窗口最大值)

【算法系列-栈与队列】队列的应用(前k高频元素 + 滑动窗口最大值)

文章目录

  • [【算法系列-栈与队列】队列的应用(前k高频元素 + 滑动窗口最大值)](#【算法系列-栈与队列】队列的应用(前k高频元素 + 滑动窗口最大值))
    • [1. 滑动窗口最大值(LeetCode 239)](#1. 滑动窗口最大值(LeetCode 239))
      • [1.1 思路分析🎯](#1.1 思路分析🎯)
      • [1.2 解题过程🎬](#1.2 解题过程🎬)
      • [1.3 代码示例🌰](#1.3 代码示例🌰)
    • [2. 前k个高频元素(LeetCode 347)](#2. 前k个高频元素(LeetCode 347))
      • [2.1 思路分析🎯](#2.1 思路分析🎯)
      • [2.2 代码示例🌰](#2.2 代码示例🌰)

1. 滑动窗口最大值(LeetCode 239)

【题目链接】239. 滑动窗口最大值 - 力扣(LeetCode)

1.1 思路分析🎯

这道题使用单调队列的方式解决

Dequeue(双端队列) + 自定义队列 -> 形成单调队列

这里我们维护一个队列:

队列出口处的数值保证是当前窗口下的最大值;

每次往队列添加元素,先将排在当前元素之前且比当前元素小的数都从队列中弹出,再将元素添加进队列中;

每次从队列弹出元素,得当元素等于队列出口元素时才可弹出,否则无需操作队列

1.2 解题过程🎬

初始化上述定义的队列,先将前k个元素添加到队列中,添加时队列会进行判断,最后留在出口位置的是当前窗口中的最大值;之后从 下标k 开始进行窗口移动,取队列出口值添加进返回数组;

直到nums数组遍历完,返回结果数组

1.3 代码示例🌰

java 复制代码
class Solution {

    class MyQueue {
        
        Deque<Integer> queue = new LinkedList<>();

        void poll(int val) {
            
            // 当元素等于队列出口元素时才可弹出,否则无需操作队列
            if (!queue.isEmpty() && queue.peek() == val) {
                queue.poll();   
            }
        }

        void add(int val) {
            // 每次往队列添加元素,先将排在当前元素之前且比当前元素小的数都从队列中弹出,再将元素添加进队列中
            while (!queue.isEmpty() && val > queue.getLast()) {
                queue.removeLast(); // 双端队列Dequeue可以从后弹出元素
            }
            queue.add(val);
        }

        // 队列出口处维护的就是最大值
        int peek() {
            return queue.peek();
        }
    }

    public int[] maxSlidingWindow(int[] nums, int k) {
        
        MyQueue queue = new MyQueue();
        int[] ret = new int[nums.length - k + 1];
        for (int i = 0;i < k;i++) {
            queue.add(nums[i]);
        }
        int len = 0;
        ret[len++] = queue.peek();
        // i = k,开始窗口移动
        for (int i = k;i < nums.length;i++) {
            queue.poll(nums[i - k]);
            queue.add(nums[i]);
            ret[len++] = queue.peek();
        }
        return ret;
    }
}

2. 前k个高频元素(LeetCode 347)

【题目链接】347. 前 K 个高频元素 - 力扣(LeetCode)

2.1 思路分析🎯

map映射 + 优先级队列

通过map来记录每个元素出现的频率,之后使用优先级队列 (这里使用小根堆,即父元素小于左右子元素,最小的元素在堆顶),通过遍历将每个map元素转换成数组并都添加进队列中,且当队列元素大于k时,将堆顶元素弹出(最小值),从而保证队列中只存在k个元素,最后弹出队列中的每个元素并取0下标值(原map的key),赋值给返回数组

2.2 代码示例🌰

java 复制代码
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        PriorityQueue<int[]> queue = new PriorityQueue<>((n1, n2) -> n1[1] - n2[1]);
        for (int x : nums) {
            map.put(x, map.getOrDefault(x, 0) + 1);
        }
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {

            int[] temp = new int[2];
            temp[0] = entry.getKey();
            temp[1] = entry.getValue();
            queue.offer(temp);
            if (queue.size() > k) {
                queue.poll();
            }
        }
        int[] ret = new int[k];
        for (int i = 0;i < k;i++) {
            ret[i] = queue.poll()[0];
        }
        return ret;
    }
}

以上便是对一些队列应用相关问题的介绍了!!后续还会继续分享其它算法系列内容,如果这些内容对大家有帮助的话请给一个三连关注吧💕( •̀ ω •́ )✧( •̀ ω •́ )✧✨

相关推荐
是小胡嘛18 分钟前
数据结构之旅:红黑树如何驱动 Set 和 Map
数据结构·算法
m0_7482550221 分钟前
前端常用算法集合
前端·算法
呆呆的猫44 分钟前
【LeetCode】227、基本计算器 II
算法·leetcode·职场和发展
Tisfy1 小时前
LeetCode 1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解
算法·leetcode·优先队列·贪心·
余额不足121381 小时前
C语言基础十六:枚举、c语言中文件的读写操作
linux·c语言·算法
火星机器人life3 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d
虽千万人 吾往矣4 小时前
golang LeetCode 热题 100(动态规划)-更新中
算法·leetcode·动态规划
arnold664 小时前
华为OD E卷(100分)34-转盘寿司
算法·华为od
ZZTC5 小时前
Floyd算法及其扩展应用
算法
lshzdq5 小时前
【机器人】机械臂轨迹和转矩控制对比
人工智能·算法·机器人