【Java 开发日记】有了解过 SpringBoot 的参数配置吗?有了解过 SpringBoot 的参数配置吗?
一、什么是单调栈?先打破 “栈” 的常规认知
提到栈,大家首先想到的是 “先进后出” 的线性结构,而单调栈,顾名思义,就是在普通栈的基础上,给元素加上了 “单调性” 的约束 —— 栈内的元素必须严格保持递增或递减(也可根据需求调整为非严格递增 / 递减)。
1.1 单调栈的核心特性
本质还是栈:完全遵循栈的 “先进后出” 规则,只是多了 “维护单调性” 的操作;
单调性可控:可维护单调递增栈(栈底到栈顶元素从小到大),也可维护单调递减栈(栈底到栈顶元素从大到小);
操作高效:每个元素最多入栈一次、出栈一次,整体时间复杂度稳定在 O (n)。
1.2 如何实现一个单调栈?
话不多说,先看基础代码实现。我们以 C++ 为例,分别实现单调递增栈和单调递减栈:
1.3 核心操作解析:为什么要 “弹出元素”?
大家可能会疑惑:“为什么要先弹出元素再入栈?” 其实这正是单调栈的核心 ——为了保证栈的单调性不被破坏。
比如维护单调递增栈时,若当前元素a[i]比栈顶元素小,说明栈顶元素 “挡路” 了:如果直接入栈,栈就会出现 “大元素在前、小元素在后” 的情况,违背递增规则。因此需要先弹出所有≥a[i]的元素,直到栈顶元素<a[i](或栈为空),再将a[i]入栈。
举个直观的例子:假设数组a = [5, 3, 7, 2],维护单调递增栈的过程:
i=1,a [i]=5:栈空,直接入栈 → 栈:[5]
i=2,a [i]=3:栈顶 5≥3,弹出 5;栈空,入栈 3 → 栈:[3]
i=3,a [i]=7:栈顶 3<7,直接入栈 → 栈:[3,7]
i=4,a [i]=2:栈顶 7≥2,弹出 7;栈顶 3≥2,弹出 3;栈空,入栈 2 → 栈:[2]
最终栈内元素为 [2],完美保持递增特性。
二、单调栈能解决什么问题?四大核心场景全覆盖
单调栈的核心应用场景,总结起来就是 “找最近最值”—— 给定一个元素,找到它左侧 / 右侧最近的、比它大 / 小的元素的位置。这四类问题看似不同,实则原理相通,掌握一种就能举一反三。
先记住一句 “口诀”:找左侧,正遍历;找右侧,逆遍历;比它大,单调减;比它小,单调增。这句话能帮你快速确定遍历方向和栈的单调性,下文会反复验证。
2.1 场景 1:找左侧最近的 “更大元素”
问题描述
给定数组a,对于每个元素a[i],找到其左侧第一个比它大的元素的下标;若不存在,返回 0。
轻松应对算法面试和竞赛中的相关问题!
更多推荐

所有评论(0)