PrepStack · Markdown HTML

单调栈找最近更大/更小

栈、单调栈与单调队列 · HTML

数学 / 逻辑形态

扫描 i;当 a[i] 满足 resolve(a[stack[-1]],a[i]) 时弹出 j 并确定其右边界 i。随后压入 i;栈中值保持所选单调方向。

识别信号

容易误判的相似信号

SignalWhy it is different
任意范围最大值查询单调栈解决最近边界,不直接回答任意在线区间极值。
滑动窗口极值候选还会因过期离窗,需双端可删的 monotonic-deque。

核心不变量

栈中索引递增,值按指定方向单调;栈内每个索引都尚未遇到能解决它的右侧元素。

状态、转移与处理顺序

ItemDefinition
State索引栈、当前 i/value、比较严格性(> 或 ≥)与答案数组。
Transition新值反复弹出被其解决的栈顶并写答案;停止时压入当前索引。
Frontier / order所有尚无右侧答案的非支配候选;被弹元素永不再有价值。

Python 骨架

def next_strictly_greater(values):
    answer = [-1] * len(values)
    stack = []  # indexes, values strictly decreasing
    for i, value in enumerate(values):
        while stack and values[stack[-1]] < value:
            j = stack.pop()
            answer[j] = i
        stack.append(i)
    return answer

正确性思路

  1. 弹出 j 时当前值比 a[j] 大,且 j 在栈期间所有中间扫描值都未能弹出它,因此 i 是第一个严格更大位置。
  2. 未弹候选按值单调保留,任何被新值支配的候选都已全部解决。
  3. 每个索引入栈一次、出栈至多一次;结束未弹者确实没有右侧更大值。

复杂度

TimeSpaceParameters
O(n)O(n)虽然有嵌套 while,但每个索引全程只 push/pop 各一次,摊还线性。

边界条件

错误模式

PatternWhy it fails / fix
栈存值却需要索引距离、边界与重复值通常要求存索引。
< 与 <= 随意替换重复值会被双计或漏计,必须由严格性定义决定。
误判嵌套循环 O(n²)用每索引至多弹一次做摊还分析。

选择与排除规则

相关模板

RelationTemplateBoundary
无过期特例单调队列维护窗口极值只按支配关系淘汰,不需要从左端过期。
边界后聚合前缀和 / 区间聚合栈找出影响区间后再用前缀计算区间量。
单调排除类比相向双指针二者都依赖安全淘汰,但候选结构不同。

原创微型例子

环节内容
Result答案索引为 [3,2,3,-1]。
Setup值 [5,2,4,7],求右侧首个严格更大索引。
Trace4 弹出 2 的索引;7 再弹 4 与 5 的索引。

Recall prompts

我的补充