当前位置: 首页 > news >正文

单调栈:高效解决边界查找问题

一、上期回顾

学完并查集 DSU:初始化、查找、合并、路径压缩,连通块、集合合并类题目直接秒杀。今天攻坚单调栈,属于刷题必备、面试常问的线性时间算法

二、单调栈核心概念

1. 什么是单调栈

栈内元素保持严格递增 / 严格递减,始终维持单调性。

  • 单调递增栈:栈底到栈顶从小到大
  • 单调递减栈:栈底到栈顶从大到小

2. 核心作用

以 O (n) 时间,快速找到每个元素左边 / 右边 第一个比它大 / 小的元素普通双重循环是 O (n²),单调栈一遍遍历 O (n) 搞定。

3. 适用场景

  • 下一个更大元素
  • 每日温度
  • 接雨水
  • 柱状图中最大矩形
  • 寻找左右边界类问题

三、单调栈工作原理

  1. 遍历数组每个元素
  2. 栈不为空,且当前元素破坏栈单调性
  3. 不断弹出栈顶,同时记录答案
  4. 把当前元素压入栈
  5. 全程维持栈内单调特性

口诀:不满足单调就弹栈,满足就入栈


四、模板 1:单调递减栈(求下一个更大元素)

题目:给数组,求每个元素右边第一个比自己大的元素

#include <iostream> #include <vector> #include <stack> using namespace std; int main() { vector<int> nums = {2,1,2,4,3}; int n = nums.size(); vector<int> res(n, -1); stack<int> st; // 存下标,保持单调递减 for(int i = 0; i < n; i++) { // 当前元素大于栈顶元素,破坏递减,弹出并更新答案 while(!st.empty() && nums[i] > nums[st.top()]) { int idx = st.top(); st.pop(); res[idx] = nums[i]; } st.push(i); } for(int x : res) cout << x << " "; return 0; }

输出:

4 2 4 -1 -1

五、模板 2:单调递增栈(求下一个更小元素)

只需要改判断条件:

while(!st.empty() && nums[i] < nums[st.top()])

六、经典例题:每日温度

题目:每日温度数组,求每一天需要等几天才会遇到更高温度

vector<int> dailyTemperatures(vector<int>& T) { int n = T.size(); vector<int> ans(n,0); stack<int> st; for(int i = 0; i < n; ++i) { while(!st.empty() && T[i] > T[st.top()]) { int idx = st.top(); st.pop(); ans[idx] = i - idx; } st.push(i); } return ans; }

七、单调栈通用刷题套路

  1. 栈中优先存下标,方便计算距离、索引
  2. 想要「右边更大」→ 用单调递减栈
  3. 想要「右边更小」→ 用单调递增栈
  4. 循环条件:不满足单调性就一直弹栈,弹栈时更新答案
  5. 最后压入当前下标

八、今日核心总结

  1. 单调栈:栈内元素维持递增 / 递减单调性
  2. 时间复杂度 O (n),每个元素入栈一次、出栈一次
  3. 核心用途:找左右第一个更大 / 更小元素
  4. 刷题固定模板:遍历 + 弹栈更新答案 + 压栈
  5. 栈存下标比存数值更灵活,适配所有边界类题目

九、课后练习

  1. 手写下一个更大元素代码,理解弹栈逻辑
  2. 独立写出每日温度单调栈解法
  3. 尝试用单调栈求「左边第一个比自己小的元素」
http://www.jsqmd.com/news/823919/

相关文章:

  • 新手8D实操指南:5步黄金流程,看完直接上手,轻松处理品质异常
  • 企业文档管理“神器”AutoVue实战:如何用它统一查看500+种格式文件(含Office/PDF/CAD)
  • 并发架构如何解决多AI模型协同难题:ChatALL的技术实现与性能优化
  • 透视 Mission Control 源码:如何构建高性能的 Agent 实时监控架构?
  • IRS2110S+IGBT半桥驱动实战:从“烧香”到稳定的调试心路
  • ChatGPT购物功能上线倒计时:已接入淘宝、京东、拼多多、Shopee、Amazon等9大平台,第10家即将官宣?
  • BilibiliDown:如何轻松下载B站视频的终极免费工具指南
  • 警惕!DeepSeek中文语境下的性别/地域/职业偏见正在 silently amplifying,48小时紧急修复方案已上线
  • 广东省离散制造业智能落地场景
  • Chrome for Testing:企业级自动化测试浏览器兼容性解决方案深度解析
  • Taotoken助力初创团队以可控成本集成大模型能力
  • efinance:3分钟快速获取四大金融市场数据的Python量化神器
  • 2025届必备的五大降AI率工具推荐榜单
  • CircuitPython与Google Coral融合:Blinka实现边缘AI硬件快速开发
  • ERP 赋能非标自动化行业:破解物料与库存管理难题
  • CAN协议全解析:从原理到实战(AI)
  • 别再折腾Better BibTeX了!用Bibnotes Formatter+MarkDBConnect搞定Zotero与Obsidian双向同步(附完整配置流程)
  • 如何将您的Android电视变身上网利器:TV Bro浏览器终极指南
  • FigmaCN:3分钟实现Figma界面完整汉化的免费神器
  • 基于CircuitPython与BLE的无线RGB调色器:从模拟信号到无线控制
  • 从Nginx到内网穿透:域名端口映射的三种实现方案对比
  • 第五课:YOLOv5-Lite模型适配AK3918AV130转换实战
  • 【Perplexity出版溯源黄金标准】:基于Crossref/DOAJ/ISSN国际数据库交叉验证的6维可信度评分模型
  • 想找靠谱正规标牌工厂厂商?这里有你不容错过的选择!
  • Mastercam加工编程许可不够用?自动回收闲置,数控车间高效
  • NotebookLM技能集成:自动化文档问答与RAG应用实践
  • 终极指南:用foo2zjs驱动100+型号打印机在Linux上完美工作
  • 深度探索AMD Ryzen处理器底层控制:揭秘SMUDebugTool的自定义调试艺术
  • 你的示波器FFT用对了吗?以泰克MDO3014为例,深入解析窗函数、分辨率与中心频率设置的实战技巧
  • 2026数据中台治理能力全景测评:七家厂商产品定位与技术路线深度拆解