单调栈速查模板

文章内容

识别信号:"下一个更大/更小"、"接雨水"、"最大矩形"、"区间最值贡献"。

口诀:求大用减、求小用增(栈内单调性)。栈里存索引。

弹栈瞬间三信息同时到手:被弹元素(高)、新栈顶(左边界)、当前 i(右边界)。三类题共用这骨架,区别只在结算公式。

单调栈原理

单调栈for 遍历数组,每轮两个动作:

  1. 弹栈(while):当前元素破坏单调性时,不停弹出栈顶。弹栈时拿到三样东西:
    1. 被弹元素(stack.pop())
    2. 左边界(弹完后 stack.peek())
    3. 右边界(当前 i)。
  2. 压栈:当前索引入栈,继续维持单调性。

代码模板:

java
Deque<Integer> stack = new ArrayDeque<>();for (int i = 0; i < n; i++) {    while (!stack.isEmpty() && nums[i] 【条件比较】 nums[stack.peek()]) {        int popped = stack.pop();          // 被弹元素        int L = stack.isEmpty() ? -1 : stack.peek();  // 左边界        // 右边界 = i,在此结算    }    stack.push(i);}

1、 下一个更大元素

java
int n = nums.length;int[] ans = new int[n];Arrays.fill(ans, -1);Deque<Integer> stack = new ArrayDeque<>();  // 存索引,栈内对应值单调递减for (int i = 0; i < n; i++) {    while (!stack.isEmpty() && nums[i] > nums[stack.peek()]) {        ans[stack.pop()] = nums[i];    }    stack.push(i);}

> 严格大于 → 严格下一个更大。要「大于等于」改 >=。这个符号是唯一需要按题调整的地方。

LC496 下一个更大元素 I

2、 接雨水

java
int trap(int[] height) {    Deque<Integer> stack = new ArrayDeque<>();    int water = 0;    for (int i = 0; i < height.length; i++) {        while (!stack.isEmpty() && height[i] > height[stack.peek()]) {            int bot = stack.pop();                  // 凹槽底部            if (stack.isEmpty()) break;             // 左边没墙,接不住            int L = stack.peek();                   // 左墙            int w = i - L - 1;                      // 宽度            int bounded = Math.min(height[L], height[i]) - height[bot];            water += w * bounded;        }        stack.push(i);    }    return water;}

if (stack.isEmpty()) break 必须写——弹完栈空说明左边没更高柱子,水从左边流走。漏掉会在 stack.peek() 处 NPE。

LC42 接雨水

3、柱状图最大矩形(哨兵技巧)

java
int largestRectangle(int[] heights) {    int n = heights.length;    int[] h = new int[n + 2];  // 首尾哨兵 0    System.arraycopy(heights, 0, h, 1, n);    Deque<Integer> stack = new ArrayDeque<>();    int ans = 0;    for (int i = 0; i < h.length; i++) {        while (!stack.isEmpty() && h[i] < h[stack.peek()]) {            int top = stack.pop();            ans = Math.max(ans, h[top] * (i - stack.peek() - 1));        }        stack.push(i);    }    return ans;}

注意这是 h[i] < h[stack.peek()](求小用增)。首哨兵保证 stack.peek() 永不为空;尾哨兵逼出栈内所有元素。System.arraycopy 目标偏移是 1,不是 0。

LC84 柱状图中最大矩形


本文由 AgentPlanFlow 生成

觉得不错?给作者点个赞吧

分类:算法

评论 (0)

无需注册,留言经站长审核后公开。

加载评论中…

单调栈速查模板 · Yinchen 的博客