每天学一个算法--单调栈(Monotonic Stack)

📘 教案 08:单调栈(Monotonic Stack)


1️⃣ 先看一个真实问题(非常关键)

给你一个数组:

text 复制代码
[2, 1, 2, 4, 3]

问题:

对每个数,找到"右边第一个比它大的数"


手算一下(你脑子会这样想)

  • 2 → 右边第一个更大是 4
  • 1 → 右边第一个更大是 2
  • 2 → 右边第一个更大是 4
  • 4 → 没有 → -1
  • 3 → 没有 → -1

如果你写代码(暴力)

python 复制代码
for i in range(n):
    for j in range(i+1, n):
        if A[j] > A[i]:
            break

👉 时间复杂度:

O(n2)\]\[ O(n\^2) \]\[O(n2)


❗问题本质

你在重复做一件事:

"找右边第一个更大元素"


2️⃣ 单调栈就是为了解决这个

一句话:

单调栈 = 用一个"有序结构",避免重复比较


3️⃣ 核心直觉(最重要)

我们从左往右扫数组:

text 复制代码
[2, 1, 2, 4, 3]

我们维护一个东西:

👉 一个"还没找到答案的元素集合"


4️⃣ 一步一步看(这是核心)


Step 1:看 2

text 复制代码
stack = [2]

👉 还不知道右边谁比它大


Step 2:看 1

text 复制代码
stack = [2, 1]

👉 1 也没找到更大的


Step 3:看 2

来了关键点👇

👉 当前 2 > 栈顶 1

说明:

text 复制代码
1 的答案找到了 → 就是 2

👉 把 1 弹出去


现在继续:

text 复制代码
stack = [2]

当前 2 == 栈顶 2 → 不弹

text 复制代码
stack = [2, 2]

Step 4:看 4(高潮)

👉 4 > 2 → 弹

👉 4 > 2 → 再弹

text 复制代码
2 → 4
2 → 4

👉 全部解决

text 复制代码
stack = []

然后:

text 复制代码
stack = [4]

Step 5:看 3

text 复制代码
stack = [4, 3]

最后

栈里剩下的:

text 复制代码
4, 3

👉 没有更大的 → -1


🔥 到这里核心已经懂了

谁被弹出,谁的答案就确定了


5️⃣ 单调栈到底是什么?

现在给定义(你已经能理解了)


定义:

一个"保持单调性"的栈结构


两种类型:


🔹 单调递减栈(常用)

栈内从底到顶:

text 复制代码
大 → 小

👉 用来找:

右边第一个更大元素


🔹 单调递增栈

text 复制代码
小 → 大

👉 用来找:

右边第一个更小元素


6️⃣ 标准模板(你可以直接教人)


找"右边第一个更大"

python 复制代码
stack = []
res = [-1]*n

for i in range(n):
    while stack and A[i] > A[stack[-1]]:
        idx = stack.pop()
        res[idx] = A[i]
    stack.append(i)

注意:

👉 栈里存的是"下标",不是值


7️⃣ 为什么一定是 O(n)


关键:

每个元素只会:

  • 入栈一次
  • 出栈一次

👉 总操作:

O(n)\]\[ O(n) \]\[O(n)


8️⃣ 常见应用(非常重要)


8.1 下一个更大元素

👉 刚讲的


8.2 柱状图最大矩形(经典难题)


8.3 股票问题

👉 找最近更大/更小


8.4 温度问题(LeetCode经典)


9️⃣ 单调栈最本质一句话

它不是"栈",而是"用栈维护顺序关系"


10️⃣ 常见错误


❌ 错误1:搞不清什么时候弹

记住一句:

👉 当前元素更强(更大/更小) → 弹栈


❌ 错误2:存值还是下标

👉 一律存下标


❌ 错误3:方向搞反

  • 左 → 右
  • 右 → 左

答案不同


教学总结

单调栈的本质是:

用一个"有序结构"一次性解决所有"下一个更大/更小"的问题

相关推荐
楚枫默寒4 小时前
Linux 编辑文件后自动添加修改日期
linux·运维·bash
苦青藤4 小时前
从零搭建 WSUS 隔离网络:完整实战指南(内网离线补丁分发)
运维·windows·microsoft
8Qi85 小时前
LeetCode 75:颜色分类(荷兰国旗问题)—— Java 题解 ✅
java·算法·leetcode·指针·排序
888CC++7 小时前
如何在 C 语言中进行程序调试?
前端·javascript·算法
天天进步20158 小时前
Python全栈项目--Python自动化运维工具开发
运维·python·自动化
Soari8 小时前
Ubuntu 根分区文件系统损坏,系统启动时自动检查失败
linux·运维·ubuntu
(●—●)橘子……8 小时前
力扣第503场周赛练习理解
python·学习·算法·leetcode·职场和发展·周赛
杨云龙UP8 小时前
Oracle Health Check巡检脚本使用SOP V2.0:从HTML原始报告→生成Word专业巡检报告→交付客户_2026-06-03
linux·运维·数据库·sql·oracle·报告·巡检
广州灵眸科技有限公司9 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) Linux虚拟机准备
linux·运维·服务器