每天学一个算法--单调栈(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:方向搞反

  • 左 → 右
  • 右 → 左

答案不同


教学总结

单调栈的本质是:

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

相关推荐
沐籽李11 小时前
HuDiff在抗体人源化项目中的工程化落地
人工智能·算法·aidd·抗体设计
依然范特东11 小时前
强化学习笔记6--IS、PPO、TD、DQN、Actor-Critic
笔记·算法
xiaoxiangsiyan11 小时前
LNMP + Redis Sentinel 高可用架构部署手册(续)
运维·网络·数据库·redis·缓存·架构·sentinel
BullSmall12 小时前
scanoss-engine 本地最简部署 & 扫描命令(Linux/Anolis OS)
linux·运维·服务器
陈聪.12 小时前
Keepalived 高可用集群:从原理到企业级实践
运维
bellus-12 小时前
Ubuntu 26.04 Miniforge3 安装与配置完整指南
linux·运维·ubuntu
5757712 小时前
户外净水器过滤效果怎么看:对照孔径、除菌率和认证三项再下单
运维·服务器
瞬间&永恒~13 小时前
【Docker】(四)Namespace 详解
运维·docker·容器
RD_daoyi13 小时前
Google核心算法不再通知!全年持续滚动更新
大数据·服务器·前端·网络·搜索引擎·.net
爱喝水的木子13 小时前
自建RustDesk私有服务器全攻略
运维·服务器