一、什么是单调栈?
单调栈是栈内元素保持单调递增或单调递减的栈结构。
它能在 O(n) 时间内解决一类"下一个更大/更小"问题。
Mermaid · 渲染中(下方为源码)
graph LR S[栈] -->|维护单调| M[单调栈] M --> NGE[下一个更大元素] M --> NSE[下一个更小元素] M --> TR[柱状图最大矩形] M --> TW[接雨水]
二、核心思想
栈里保存"待匹配"的元素下标/值。
当前元素入栈时,把破坏单调性的栈顶全部弹出,弹出的就是"答案"。
例:求"下一个更大元素"。
nums = [2, 1, 2, 4, 3]
单调递增栈(栈顶最小 → 栈底最大,遇到更大就弹),每个元素对应"下一个更大":
i=0 (2): 栈空 → push(0)。栈 = [2]
i=1 (1): 1 < 2,**保持递增**(递增栈,1 让栈更"递增"),入栈。栈 = [2, 1]
i=2 (2): 2 > 1 → 弹出 1(1 的下一个更大就是 2,ans[1] = 2)。
2 == 2,不弹(严格大于才弹)。
push(2)。栈 = [2, 2]
i=3 (4): 4 > 2 → 弹出 2(ans[2] = 4)。
4 > 2 → 弹出 2(ans[0] = 4)。
栈空,push(3)。栈 = [4]
i=4 (3): 3 < 4,不弹。push(4)。栈 = [4, 3]
剩余栈中 [3, 4] 都没有"下一个更大",ans 默认 -1。
最终答案:[4, 2, 4, -1, -1]
口诀:求下一个更大 → 单调递减栈(栈顶最小),遇更大就弹。 求下一个更小 → 单调递增栈(栈顶最大),遇更小就弹。
三、模板
int[] nextGreater(int[] nums) {
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[stack.peek()] < nums[i]) {
ans[stack.pop()] = nums[i];
}
stack.push(i);
}
return ans;
}