单调队列讲解
单调队列看完这篇滑动窗口最小值再也难不住你目录从一道题开始单调队列到底是个啥为什么普通 queue 不行正确的写法deque 结构体例题演练滑动窗口最小值手动模拟过程代码模板复杂度与适用场景总结从一道题开始先看一个很经典的题给你一个长度为 (n) 的数组再给一个窗口大小 (k)窗口从左往右滑每次输出窗口里的最小值。比如数组是4 2 5 1 3 6 2 7(k 3)滑动过程长这样[4,2,5] → 最小值 2 [2,5,1] → 最小值 1 [5,1,3] → 最小值 1 [1,3,6] → 最小值 1 [3,6,2] → 最小值 2 [6,2,7] → 最小值 2最后输出2 1 1 1 2 2。数据范围 (n \le 2\times10^5)要是每滑一次就把窗口里的数扫一遍找最小值复杂度 (O(nk))妥妥超时。这时候就需要一个能快速维护窗口极值的结构——单调队列。单调队列到底是个啥名字听着有点唬人其实很简单。单调队列就是一个里面的元素值始终保持单调的队列。比如求最小值我们让队列从队头到队尾递增这样队头永远是最小的那个。它和普通队列最大的不同在于我们不但能从队头删元素还可以从队尾删。所以必须用双端队列deque来实现。另外队列里我们一般存的是元素的下标有时候也顺手把值存上这样既能比较值的大小又能判断元素是不是已经滑出窗口了。为什么普通 queue 不行我们可能凭感觉写出这种代码看着好像挺对structnode{ll id,v;};queuenodeq;for(ll i1;in;i){while(q.size()q.front().idi-k)q.pop();while(q.size()q.front().va[i])q.pop();// 想删掉比新元素大的q.push({i,a[i]});if(ik)coutq.front().v ;}这个代码有两个大问题只能操作队头碰不到队尾第二个while里想删掉所有“比新元素大”的值但queue只能从队头删真正该删的大值往往在队尾根本够不着。单调性维护错位置维护单调递增应该从队尾把那些大的弹出去而不是在队头瞎折腾。所以想写单调队列queue可以直接弃用上deque。正确的写法deque 结构体我们用dequenodestructnode{ll id;// 下标ll v;// 值};dequenodeq;整个算法就四步一步都不能乱清理元素队头窗口右边界是i左边界是i - k 1。如果队头的下标比左边界还小说明它已经滑出去了直接pop_front()。while(!q.empty()q.front().idi-k1)q.pop_front();从队尾维护单调性我们要递增队列所以只要队尾元素的值大于等于当前新值a[i]它就再也不可能成为窗口的最小值了果断pop_back()。while(!q.empty()q.back().va[i])q.pop_back();新元素入队处理好前面的后把当前元素{i, a[i]}塞到队尾。q.push_back({i,a[i]});取答案当窗口形成以后i k队头元素就是当前窗口的最小值直接输出。if(ik)coutq.front().v ;// 输出单个值空格分开注意输出语句里cout和之间可以保留风格我这里为了看得清保留了一个空格实际你的模板里都是连写的coutq.front().v ;也没问题后面例题代码全部统一成紧凑格式。例题演练滑动窗口最小值题目是开头那个完整代码#includebits/stdc.husingnamespacestd;#definerep(i,a,n)for(ll ia;in;i)typedeflonglongll;constintmaxn2e510;structnode{ll id;// 元素在原数组中的下标ll v;// 元素的值};ll a[maxn];dequenodeq;// 双端队列维护单调递增ll n,k;intmain(){cinnk;rep(i,1,n){cina[i];// 1. 弹出窗口外的元素while(!q.empty()q.front().idi-k1)q.pop_front();// 2. 从队尾删掉所有大于等于当前值的元素维持递增while(!q.empty()q.back().va[i])q.pop_back();// 3. 当前元素入队q.push_back({i,a[i]});// 4. 窗口形成输出队头最小值if(ik)coutq.front().v ;}return0;}测试样例输入8 3 4 2 5 1 3 6 2 7输出2 1 1 1 2 2手动模拟过程拿上面的样例一步一步走理解更深刻。队列里展示的是(下标:值)窗口大小k 3。ia[i]操作后的队列递增窗口范围输出14(1:4)[1]-22(2:2)[1,2]-35(2:2) (3:5)[1,2,3]241(4:1)[2,3,4]153(4:1) (5:3)[3,4,5]166(4:1) (5:3) (6:6)[4,5,6]172(4:1) (7:2)[5,6,7]287(4:1) (7:2) (8:7)[6,7,8]2看点细节i2时a[2]2比队尾的4小所以4被弹出只留下2。i4时新值1比队里的5和2都小它俩全被弹走同时队头的(2:2)因为下标2已经小于窗口左边界2也被清掉。最后只剩(4:1)窗口最小值变成1。后面就一直按这个逻辑走非常丝滑。代码模板为了方便以后直接用我把求最小值和最大值的模板都贴出来只改数组名和窗口大小就行。#includebits/stdc.husingnamespacestd;#definerep(i,a,n)for(ll ia;in;i)typedeflonglongll;constintmaxn2e510;structnode{ll id,val;};ll a[maxn];dequenodeq;// 滑动窗口最小值单调递增队列voidsolve_min(ll n,ll k){q.clear();rep(i,1,n){while(!q.empty()q.front().idi-k1)q.pop_front();while(!q.empty()q.back().vala[i])q.pop_back();q.push_back({i,a[i]});if(ik)coutq.front().val ;}}// 滑动窗口最大值把 改成 就行变成递减队列voidsolve_max(ll n,ll k){q.clear();rep(i,1,n){while(!q.empty()q.front().idi-k1)q.pop_front();while(!q.empty()q.back().vala[i])q.pop_back();q.push_back({i,a[i]});if(ik)coutq.front().val ;}}复杂度与适用场景时间复杂度每个元素最多入队一次、出队一次每一步都是 (O(1))整体(O(n))。空间复杂度队列里最多存 (k) 个元素(O(k))。除了这种裸的滑动窗口极值单调队列还常用来优化DP比如“可从前面长度为 (k) 的区间转移”的题目把转移的 (O(k)) 变成 (O(1))相当好用。总结单调队列的核心就是双端队列维护单调性存下标、删过期、删无效、取队头。求最小值用递增队列求最大值用递减队列比较符号换一下就行。一般不用用queue来写它没有pop_back()天生残疾。动手模拟一遍流程以后遇到这类题基本可以秒。

相关新闻

Rust vs Go Web 框架性能对比:Axum、Actix、Gin、Fiber 的 10 万并发压测报告

Rust vs Go Web 框架性能对比:Axum、Actix、Gin、Fiber 的 10 万并发压测报告

Rust vs Go Web 框架性能对比:Axum、Actix、Gin、Fiber 的 10 万并发压测报告 一、技术选型的务实困局:语言性能差距到底被夸大了多少 在决定新项目的 Web 框架技术栈时,Rust 和 Go 是两个最终的候选者。Go 的支持者列举 Gin/Fiber 的生态成…

2026/10/18 21:56:56 阅读更多 →
羽毛球动作生成对抗网络:用 GAN 合成训练数据的可行性验证

羽毛球动作生成对抗网络:用 GAN 合成训练数据的可行性验证

羽毛球动作生成对抗网络:用 GAN 合成训练数据的可行性验证 一、标注数据荒:300 小时视频只能标出 2000 个有效击球动作 在运动分析系统的开发中,最大的瓶颈不是模型架构,而是高质量标注数据的匮乏。实际采集的 300 小时训练视频中…

2026/10/19 1:29:34 阅读更多 →
UE4 GenerateProjectFiles报错:平台名无效的深度排查与修复指南

UE4 GenerateProjectFiles报错:平台名无效的深度排查与修复指南

1. 项目概述:UE4引擎GenerateProjectFiles报错深度解析如果你正在使用虚幻引擎4(UE4)进行项目开发,尤其是在团队协作或新环境搭建时,大概率会用到GenerateProjectFiles这个命令。它的作用是根据你的项目.uproject文件&…

2026/10/16 22:24:38 阅读更多 →

最新新闻

Flutter性能优化:benchmark_harness鸿蒙化适配与微基准测试实战

Flutter性能优化:benchmark_harness鸿蒙化适配与微基准测试实战

做 Flutter 性能优化的人多少都和 benchmark_harness 打过交道——这是 Dart 官方维护的微基准测试库,核心价值是让你用标准化的方式量化函数耗时,而不是靠 print 打时间戳拍脑袋。但大多数人没用它跑过鸿蒙环境。我这次要交代的,就是把它完整…

2026/10/19 14:19:06 阅读更多 →
Flask + uni-app 电商小程序实战:从后端设计到前端联调

Flask + uni-app 电商小程序实战:从后端设计到前端联调

如果你正打算做一个电商类的购物小程序,又不想把前后端拆得太开、来回折腾,那 Python Flask uni-app 这套组合,我实测下来很适合。我最近完整做了一个商城购物平台的电商小程序,从数据库设计、后端接口到前端页面全部自己写。标题…

2026/10/19 14:19:06 阅读更多 →
AI写作如何支撑公众号矩阵:一个人批量运营多号的完整方法

AI写作如何支撑公众号矩阵:一个人批量运营多号的完整方法

做公众号矩阵这件事,我是从去年才开始认真折腾的。起因很直接——手头几个号分别对应不同的内容方向,靠我一个人晚上下班后一篇篇手工码字,根本写不过来。后来我把AI写作真正纳入生产流程,才摸索出一套一个人也能批量运营多个账号…

2026/10/19 14:19:06 阅读更多 →
代码评审工程化:用open-code-review构建高效自动化评审体系

代码评审工程化:用open-code-review构建高效自动化评审体系

代码评审这事儿,做了这么多年,我见过太多团队把 Review 做成“走过场”。打开 Pull Request 页面,扫一眼标题,鼠标滚轮滑到最底部,点一下 Approve,完事。你以为你在做质量保障,实际上你只是在给…

2026/10/19 14:19:05 阅读更多 →
Open Code Review:基于Git Diff与本地LLM Agent的可审计代码评审范式

Open Code Review:基于Git Diff与本地LLM Agent的可审计代码评审范式

1. “open-code-review”不是个工具名,而是一类新型代码评审范式的代号最近在几个技术社区里频繁看到“open-code-review”这个词,它不像 git clone 或 npm install 那样指向某个具体命令,也不像 SonarQube、CodeClimate 那样对应一个安装包。…

2026/10/19 14:19:05 阅读更多 →
基于Socket的TCP Linux聊天系统实战:从协议设计到文件传输

基于Socket的TCP Linux聊天系统实战:从协议设计到文件传输

做过Linux网络编程的人,大概率都自己动手写过聊天程序。但很多人的练习项目在“能收发字符串”这一步就停了,再往上基本就是查文档、复制粘贴、能跑就算完。这里想完整分享一个我自己完整搭过的项目,基于Socket的TCP协议Linux聊天系统&#x…

2026/10/19 14:17:57 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →