单调栈 —— 1.基本概念与核心算法

发布于:2025-04-13 ⋅ 阅读:(13) ⋅ 点赞:(0)

在这里插入图片描述

1. 基本概念

1.1 知识预备

在理解单调栈之前,我们需要先掌握两个基础概念:栈(Stack)单调性(Monotonicity)

什么是栈(Stack)

栈是一种**后进先出(LIFO, Last-In-First-Out)**的数据结构:

  • 新元素始终压入栈顶(push
  • 移除元素也始终从栈顶弹出(pop

我们可以把栈想象成一叠书:

  • 你只能从最上面放/取书(栈顶)
  • 先放进去的书在下面,必须等上面的书移除后才能访问

基本操作:

  • push(x):将元素 x 压入栈顶
  • pop():弹出栈顶元素
  • top():查看栈顶元素但不弹出
  • empty():判断栈是否为空

1.2 什么是单调栈

单调栈是栈的一种特殊使用方式,其特点是:始终保持栈内元素有序(单调递增或递减)

常见的两种形式:

  • 单调递增栈:栈中元素从栈底到栈顶递增(栈顶最小)
  • 单调递减栈:栈中元素从栈底到栈顶递减(栈顶最大)

例如,维护一个单调递增栈的过程:

初始空栈:[]
压入 3: [3]
压入 5: [3, 5] ✅(递增)
压入 2: ❌(2 小于栈顶 5,弹出 5,再比较 3,直到栈递增)最后的结果是 [2]

单调栈的本质:在压入元素时,通过弹出不满足单调性的栈顶元素,从而维护一个有序结构,方便我们高效地找到“下一个更大/小”的元素。

单调栈常解决的问题类型

适合使用 单调栈 的题目,通常具有以下几个显著特点:

1. 需要找“第一个满足条件的前/后缀元素”

比如:

  • 右边第一个比自己大的元素
  • 左边第一个比自己小的元素
  • 最近的更高温度、更高价格、更大柱子

👉 本质:找某个方向上第一个满足单调性条件的元素

2. 数组或序列题,且有“元素之间的相对关系”
  • 题目一般给定一个 一维数组/序列
  • 要你找出元素之间的顺序比较关系

例如:

  • 每个元素右边第一个更大的数
  • 每个元素左边第一个更小的位置
3. 暴力解法是 O(n²),但可以优化为 O(n)

如果你写出暴力法是两层循环查“后面第一个符合条件的元素”,就可以考虑:

是否能用单调栈来代替嵌套循环

单调栈能做到:

  • 每个元素最多被压入一次,弹出一次
  • 时间复杂度稳定在 O(n)
4. 问题与“范围”、“跨度”或“影响范围”有关

如:

  • 当前元素往左/右能扩展到多远
  • 柱状图中每个柱子形成的最大矩形
  • 股票价格连续上升/下降天数

这些问题都和某个元素能“影响”多远有关,适合用单调栈维护边界。


1.3 单调栈的常见例题

应用方向 示例题目 说明
找最近更大/小元素 LeetCode 496(下一个更大元素) 线性替代暴力嵌套循环
求区间最值相关 LeetCode 84(柱状图最大矩形) 栈维护高度索引
序列分析 LeetCode 739(每日温度) 找出等待更高温度的天数
股票分析 LeetCode 901(股票价格跨度) 求比当前价格小的最近时间间隔

2. 核心算法

2.1 解题思路(以“下一个更小元素”为例)

  • 使用一个栈,从左到右遍历数组
  • 当当前元素比栈顶元素小:说明找到“右侧第一个更小元素”
  • 栈中维护一个单调递增序列的索引

2.2 代码实现(Python 示例)

def next_smaller_elements(nums):
    res = [-1] * len(nums)
    stack = []
    for i in range(len(nums)):
        while stack and nums[i] < nums[stack[-1]]:
            idx = stack.pop()
            res[idx] = nums[i]
        stack.append(i)
    return res

2.3 灵活应用

变体需求 应对策略
查找前一个更小/更大元素 从右往左扫描
需要记录距离而不是值 栈中存索引,使用 i - stack[-1]
找所有区间贡献 与前一个/后一个满足条件元素组合出区间

3. 总结

对于一个新手而言,单调栈往往是让人感到 amazing 的方法,需要结合题目的特点进行分析,当满足前面提到的某一些特点的时候,可以考虑使用单调栈来解决问题。

单调栈只是一个工具,它甚至不能说是某一种算法。因此有时候考察的可能是单调栈与其他算法的结合,比如 DP 之类的。

这里对本文做个小结:

  • 单调栈是一个高效解决序列型“最值查找”问题的利器
  • 本质是维护一个具有顺序性质的栈
  • 实现时注意:栈中通常存储索引而非值
  • 单调栈常作为经典面试题考点,应熟练掌握其基本模板并灵活变形

更多的例子将会结合力扣、洛谷的题目进一步展开,感兴趣的小伙伴们不妨关注一波 ~

感谢各位小伙伴们的 阅读点赞评论关注 ~ 希望本文能帮助到各位,共勉 ~

在这里插入图片描述

Smileyan
2025.04.12 22:17


网站公告

今日签到

点亮在社区的每一天
去签到