解题思路1:
双指针
提交代码:
class Solution {
public int trap(int[] height) {
int left=0,right=height.length-1,min,sum=0;
while(left<right) {
min=height[left]<height[right]?height[left]:height[right];
if(height[left]<height[right]) {
left++;
while(left<right&&height[left]<min)
sum+=min-height[left++];
}
else {
right--;
while(left<right&&height[right]<min)
sum+=min-height[right--];
}
}
return sum;
}
}
运行结果:

解题思路2:
单调栈
我们从左到右遍历所有的柱子,使用栈来保存柱子的坐标,保存的标准如下:
当当前柱子高度低于栈顶坐标位置的高度,则将下一个柱子的坐标入栈;
当当前柱子高度高于栈顶坐标位置的高度,则将栈中的元素不断弹出(pop)直至坐标为栈顶元素数值的柱子高于当前柱子的高度。
即我们维护的是一个单调递减栈,同时柱子之间能积蓄的雨水是柱子之间坐标的差值减一。
以例题中的柱子高度数组 [0,1,0,2,1,0,1,3,2,1,2,1] 为例,对计算的过程进行说明:
假设我们有一个栈stack=[] 初始情况下为空
坐标为0的柱子,高度为0,将坐标入栈:
stack=[0]
累计可积蓄雨水量为0
坐标为1的柱子,高度为1。
当前柱子高度高于坐标为栈顶的柱子高度(栈顶元素为0,坐标为0的柱子高度为0)
则stack出栈,能够积蓄的雨水量为1-0-1=0(柱子坐标的差值-1)
同时将当前的柱子坐标入栈:
stack=[1]
累计可以积蓄雨水量为0
坐标为2的柱子,高度为0,高度低于1,入栈:
stack=[1,2]
累计可积累雨水量为0
坐标为3的柱子,高度为2,弹出所有高度低于当前柱子的柱子坐标,同时将当前柱子坐标入栈:
stack=[3]
累计可积累雨水量为3-1-1=1
坐标为4的柱子,高度为1,入栈;
stack=[3,4]
累计可积蓄雨水量为1
坐标为5的柱子,高度为0,入栈:
stack=[3,4,5]
累计可积蓄雨水量为1
坐标为6的柱子,高度为1,弹出栈顶元素直至坐标为栈顶元素的柱子高度高于当前柱子:
stack=[3]
累计可积蓄雨水量为1+(6-4-1)=1+1=2
坐标为7的柱子,高度为3,出栈操作后,有:
stack=[7]
累计可积蓄的雨水量为2+(7-3-1)=2+3=5
坐标为8的柱子,高度为2,入栈:
stack=[7,8]
累计可积蓄雨水量为5
坐标为9的柱子高度为1,入栈:
stack=[7,8,9]
累计可积蓄雨水量为5
坐标为10的柱子高度为2,出栈:
stac=[7,10]
累计可积蓄雨水量为5+(10-8-1)=5+1=6
坐标为11的柱子高度为1,入栈:
stack=[7,10,11]
累计可积蓄雨水量为6
至此已经遍历完所有的柱子,同时可以得到累计的可积蓄雨水量为6
提交代码:
class Solution{
public int trap(int[] height) {
Stack<Integer> stack=new Stack<Integer>();
int i=0,water=0;
int left,base,depth;
while(i<height.length) {
if(stack.isEmpty()||height[stack.peek()]>height[i])
stack.push(i++);
else {
base=stack.pop();
if(!stack.isEmpty()) {
left=stack.peek();
depth=Math.min(height[left],height[i])-height[base];
water+=depth*(i-left-1);
}
}
}
return water;
}
}
运行结果:

本文深入探讨了积水计算中的双指针与单调栈两种算法,通过实例详细解析了每种算法的工作原理,以及如何在积水计算问题中高效地找出最大积水容量。
346

被折叠的 条评论
为什么被折叠?



