【LeetCode】升级打怪之路 Day 12:单调队列

今日题目:

  • 239. 滑动窗口最大值 | LeetCode

今天学习了单调队列这种特殊的数据结构,思路很新颖,值得学习。

Problem:单调队列 【必会】

与单调栈类似,单调队列也是一种特殊的数据结构,它相比与普通的 queue,增加了一个新的接口 max() 来获取当前队列的最大值

新增的 max() 是我们选用这个数据结构的最重要原因,单调队列不仅仅可以通过 offer()poll() 接口来实现 FIFO 的元素进出顺序,还额外增加了 max() 接口让我们获取到当前队列中的最大元素。

单调队列主要用来解决下面这个场景:我们会时刻向一个集合中增加新元素或减少旧元素,同时每次可以获取到当前这个集合中的最大值。优先级队列也可以满足这个需求,但优先级队列无法满足 FIFO 的元素进出顺序,这也是必须使用单调队列的原因。

假如有一个数组 window,并知道它的最大值是 A,此时向 window 增加一个新元素 B,我们只需要比较 A 和 B 就可以得到当前 window 中的最大值;但如果删除一个旧元素 C,就麻烦了,因为如果这个删除的 C 恰恰就是最大值 A,那么最大值就要重新遍历 window 来寻找了,从而导致复杂度飙升。这就是单调队列所需要解决的难题。

下面看一下单调队列的经典应用:滑动窗口最大值

LC 239. 滑动窗口最大值 【classic】 ⭐⭐⭐⭐⭐

239. 滑动窗口最大值 | LeetCode

如果我们能够实现数据结构“单调队列” MonoQueue,那我们就每次向右滑动我们的窗口时,向 monoQueue 中新增一个窗口右边的新元素,移除一个窗口左边的旧元素,然后调用 max() 接口获取当前窗口的最大值,就可以计算出题目所需要的最终结果。

在这里插入图片描述

所以重点在于如何实现 MonoQueue。

我们需求的关键是:需要能够快速得知当前队列中的最大值。由于窗口滑动时是有顺序的,先进入的元素一定会先出去,所以如果新进入的一个元素,那么比它老的还比它小的那些元素就永远不可能成为当前队列中的最大值了,因为老元素一定会比新元素更早地离开队列。所以,每次在入队一个新元素时,就可以把队列中比他小的元素都抛弃掉了

在这里插入图片描述
如上图,当元素 5 进入队列后,就可以一下子把 4、3、2、1 全给抛弃掉了,因为这些旧元素在队列的时候 5 一定在,所以这些旧元素一定成不了“当前队列的最大值”。

根据以上分析,单调队列 MonoQueue 的实现如下:

class MonoQueue {
    private Deque<Integer> maxQ = new LinkedList<>();
    
    public void offer(int num) {
        // 将小于 num 的元素全部删除
        while (!maxQ.isEmpty() && maxQ.getLast() < num) {
            maxQ.removeLast();
        }
        // 将 num 加入队尾
        maxQ.addLast(num);
    }

    public int max() {
        return maxQ.getFirst();  // 单调队列,队首就是最大元素
    }

    public void poll(int n) {
        if (maxQ.getFirst() == n) {  // 判断需要移除的是否是队首,如果不是的话,就是比队首小还比队首老的元素,已经被移除了,那就啥也不用干
            maxQ.removeFirst();
        }
    }
}

这里有两个易错点:

  • offer() 函数实现中,第一步删掉掉小于 num 的元素,但注意别把等于它的元素删除了,因为如果把相等的元素也删掉的话,实现 poll() 接口时,就不太好判断 队首最大元素 是否就是我们当前需要 poll 的元素了(我们是通过值相等来判断的)
  • 在实现 poll() 函数时,其参数 n 表示期待删除的元素,因为我们这个 MonoQueue 并没有保留全部入队元素,所以当需要删除一个已经被删除的元素时,poll() 接口只需要立刻返回就可以了。

在实现了 MonoQueue 后,我们解决这个问题就容易多了:

    public int[] maxSlidingWindow(int[] nums, int k) {

        MonoQueue monoQueue = new MonoQueue();
        List<Integer> result = new ArrayList<>();

        // 将前 k-1 个元素填充到队列中
        for (int i = 0; i < k - 1; i++) {
            monoQueue.offer(nums[i]);
        }

        for (int i = k - 1; i < nums.length; i++) {
            // 加入窗口右边的新元素
            monoQueue.offer(nums[i]);
            // 获取窗口内最大元素,并加入到结果集中
            result.add(monoQueue.max());
            // 移除窗口左边的旧元素
            monoQueue.poll(nums[i - k + 1]);
        }

        return result.stream().mapToInt(Integer::valueOf).toArray();
    }

通过这个题,我们可以更加深入地理解单调队列的具体用法。在有些情况下,我们除了在 MonoQueue 里面维护一个 maxQ 之外,还可以额外维护一个标准的 queue,从而对外表现出正常的 offer() 和 poll() 接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/425613.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot3-核心原理

1. 事件和监听器 1. 生命周期监听 场景&#xff1a;监听应用的生命周期 1. 监听器-SpringApplicationRunListener 自定义SpringApplicationRunListener来监听事件&#xff1b; 编写SpringApplicationRunListener 实现类在 META-INF/spring.factories 中配置 org.springfram…

Windows操作系统中各种功能、快捷键

目录 引言一、系统1.任务管理器&#xff08;当前进程属性&#xff09;2.画图板3.计算器4.CMD命令行窗口5.控制面板6.记事本7.写字板 二、浏览器1.打开开发者工具2.页面搜索 三、AcWing1.替换2.对多处进行相同操作3.光标变为下划线 引言 由于本专业是计算机专业&#xff0c;所以…

【Spring Boot】实现全局异常处理

1.定义基础异常接口类 /*** description: 服务接口类* author: MrVK* date: 2021/4/19 21:39*/ public interface BaseErrorInfoInterface {/*** 错误码* return*/String getResultCode();/*** 错误描述* return*/String getResultMsg(); } 2.定义错误处理枚举类 /*** desc…

LeetCode 热题 100 | 图论(三)

目录 1 前缀树 1.1 什么是前缀树 1.2 如何构建前缀树 2 208. 实现 Trie&#xff08;前缀树&#xff09; 菜鸟做题&#xff0c;语言是 C 1 前缀树 1.1 什么是前缀树 前缀树&#xff0c;也被称作字典树&#xff08;Trie&#xff09;或者键树&#xff0c;是一种用于检…

Mysql运维篇(七) 部署MHA--完结

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 一、MHA软件构成 Manager工具包主要包括以下几个工具&#xff1a; masterha_manger 启…

BY组态功能清单

演示地址 &#xff1a;http://www.byzt.net:60/sm/ 官网地址&#xff1a;http://www.hcy-soft.com BY组态是一款非常优秀的纯前端的【web组态插件工具】&#xff0c;可无缝嵌入到vue项目&#xff0c;react项目等&#xff0c;由于是原生js开发&#xff0c;对于前端的集成没有框架…

VUE3项目学习系列--项目创建(一)

一、项目搭建 1、环境要求&#xff1a;vite(node.js版本16) 构建项目&#xff0c;pnpm进行包管理&#xff0c;速度快、高效&#xff1b; 安装node.js&#xff0c;在node官方下载安装即可&#xff1b;pnpm安装&#xff0c;使用如下命令 npm i -g pnpm 2、项目创建&#xff1…

python学习笔记------元组

元组的定义 定义元组使用小括号&#xff0c;且使用逗号隔开各个数据&#xff0c;数据是不同的数据类型 定义元组字面量&#xff1a;(元素,元素,元素,......,元素) 例如&#xff1a;(1,"hello") 定义元组变量&#xff1a;变量名称(元素,元素,元素,......,元素)…

GitHub提交代码步骤

在个人主页找到setting: 在左侧最下面找到“开发者设置” 然后生成一个token&#xff1a; 全部勾上&#xff1a; 复制好token: 在本地仓库运行 git init 保所有的本地更改都已经提交。这包括新文件的添加以及现有文件的修改。 使用git status来查看当前有哪些更改是未跟踪或…

vue3 vite项目一运行就401(Unauthorized)

问题&#xff1a;项目一执行&#xff1a; pnpm run dev, 启动就出错&#xff0c; Failed to load resource: the server responded with a status of 401 (Unauthorized) 分析&#xff1a; 项目之前是正常运行的&#xff0c;没有问题&#xff0c;回溯刚刚改动&#xff0c;还原…

快速幂(求解原理+例题)

目录 反复平方法&#xff08;快速幂&#xff09;&#xff1a; 代码&#xff1a; 例题&#xff1a;快速幂求逆元 作用&#xff1a; 快速求出 的结果。 时间复杂度&#xff1a; O(logk) 如果使用一般做法&#xff0c;从1循环到k&#xff0c;时间复杂度是O(k) 反复平方法&am…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的行人车辆检测与计数(Python+PySide6界面+训练代码)

摘要&#xff1a;开发行人车辆检测与计数系统对于提升城市交通管理和监控系统的效率至关重要。本篇博客详细介绍了如何利用深度学习构建一个行人车辆检测与计数系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并结合了YOLOv7、YOLOv6、YOLOv5…

8.WEB渗透测试-Linux基础知识-Linux基础操作(二)

内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;7.WEB渗透测试-Linux基础知识-Linux基础操作&#xff08;一&#xff09;-CSDN博客 Tab键是补全命令&#xff0c;双击两下Tab键&#xff0c;会告诉你能补全的所有命令 文本编辑器指令&#xff1a;vi 输入vi 1…

技术派Redis实现作者白名单

通过技术派发文章的时候&#xff0c;发文章会先通过审核&#xff0c;只有通过审核在会在网站上进行展示。是不是所有的作者都要经过审核呢&#xff1f; 当然不是&#xff0c;在这里做了一个白名单&#xff0c;在白名单中的用户发文之后是不需要进入审核的&#xff0c;可以直接…

终于找到你!数字化时代的秘密武器

在数字化时代&#xff0c;纸张依旧扮演着重要的角色&#xff0c;无论是平板的电子笔记背景纸张&#xff0c;还是纸质纸张&#xff0c;亦或者你想要一个美观的纸张背景图。一张合适的纸张能大大提升我们的工作和学习效率。今天&#xff0c;我们将探索三款网站&#xff0c;它们可…

libreoffice免费的office软件

https://mirrors.ustc.edu.cn/tdf/libreoffice/stable/24.2.1/win/x86_64/LibreOffice_24.2.1_Win_x86-64.msi

Jetson Xavier NX 开发板Ubuntu18.04 安装arduino IDE详细步骤

Jetson 平台是arch架构&#xff0c;官网上面几乎都是x86或者arm64的这两种错误版本都存在匹配问题无法使用&#xff0c;不要下载不要下载&#xff01; uname -a #版本查询1.正确下载打开方式 https://downloads.arduino.cc/arduino-1.8.19-linuxaarch64.tar.xz选择自己想要下…

Codeforces Round 930 (Div. 2)

substr时间复杂度O&#xff08;N&#xff09;&#xff0c;不能一遍遍找&#xff0c;会超时 #include<iostream> #include<algorithm> #include<vector> #include<map> using namespace std; const int N5e510; map<string,int>mp; vector<…

Vision Pro开发者学习路线

官方给到的Vision Pro开发者学习路线&#xff1a; 1. 学习基础知识&#xff1a; - 学习 Xcode、Swift 和 SwiftUI 的基础知识&#xff0c;包括语法、UI 设计等。 - 掌握 ARKit 和 SwiftUI 的使用&#xff0c;了解如何创建沉浸式增强现实体验。 2. 学习 3D 建模&#xf…

基于springboot+vue的网上服装商城

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…