单调栈是解决接雨水问题最经典高效的方法,通过维护递减下标栈,一次遍历即可在O(n)时间内为每个柱子快速定位左右首个更高柱子,进而计算凹槽水量。

单调栈是解决接雨水问题最经典且高效的方法之一,核心在于利用栈维护“递减序列”,快速定位每个柱子左边和右边第一个比它高的柱子,从而算出该位置能存多少水。
为什么用单调栈?
接雨水的关键是:对每个位置 i,能接的水量 = min(左边最高柱子, 右边最高柱子) - 当前高度(需 ≥ 0)。暴力法要为每个 i 扫描左右,时间 O(n²);而单调栈能在一次遍历中,以 O(1) 均摊代价找到“最近的更大元素”,把总时间降到 O(n)。
栈里存的是下标(不是高度),保持栈内对应高度严格递减——这样当遇到一个更高的柱子时,栈顶元素就找到了它的“右边界”,而栈中下一个元素就是它的“左边界”。
单调栈解法三步走
- 初始化空栈,从左到右遍历每个柱子下标 i
- 若当前高度 height[i] > 栈顶对应高度,说明栈顶位置找到了“右边界”:弹出栈顶作为“凹槽底部”,此时新栈顶是“左边界”,i 是“右边界”,三者可算水量
- 计算水量公式: (min(height[left], height[right]) - height[bottom]) × 宽度,其中宽度 = i - stack.peek() - 1(注意是下标差)
关键细节注意
栈中存下标更灵活,方便算宽度、查高度;每次只处理“能形成凹槽”的弹出动作;同一个下标可能被多次用于不同凹槽(比如中间矮柱被左右高柱夹住多次);边界情况(如全递增或全递减)栈最后可能非空,但那些位置无法形成凹槽,无需额外处理。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
例如 heights = [0,1,0,2,1,0,1,3,2,1,2,1],当 i=3(height=2)时,栈内为 [0,1,2](对应高度 0,1,0),弹出下标 2(高度 0)后,left = 1(高度 1),right = 3(高度 2),宽度 = 3-1-1 = 1,水量 = min(1,2)-0 = 1。
代码结构简洁版(伪逻辑)
// Stack
// int water = 0;
// for (int i = 0; i // if (!stack.isEmpty() && height[i] > height[stack.peek()]) {
// int bottom = stack.pop();
// if (!stack.isEmpty()) {
// int left = stack.peek(), right = i;
// water += (Math.min(height[left], height[right]) - height[bottom]) * (right - left - 1);
// }
// }
// stack.push(i);
// }

















