题目:接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
答案
class Solution {
public int trap(int[] height) {
if (height.length==0){
return 0;
}
int ans=0;
int bottom,left,len,he;
//创建栈,peek()方法取出栈顶,pop()方法取出栈顶并删除栈顶,empty()方法判断是否为空
//使用栈存放每个墙的序号
Stack<Integer> stack=new Stack<Integer>();
stack.push(0);
for (int i=1;i<height.length;i++){
//判断当前高度是否大于栈顶高度
while (height[i] >= height[stack.peek()] && !stack.empty()) {
//假设当前栈里存放序列的高度为{4,2,1},当前i所有的高度为3
//如果大于则取出栈顶,并删除栈顶,将栈顶作为底部。
//即取出1,当前栈为2,4,2
bottom = height[stack.pop()];
if (stack.empty()){
break;
}
//因为小于栈顶才能入栈,则现在的栈顶一定大于之前取出的栈顶,取出当前栈顶
//left,bottom,和height[i]这三个数会出现一个凹进去的情况
left=stack.peek();
//算出left和height[i],因为两者之间可能并不连续
// 比如下次循环,4和2和3因为取出了1不连续,所以用序号存入栈,方便取出宽度
len=i-left-1;
//计算凹进去的面积
//当不连续时,算到的当前的情况时,那些小的凹槽已经计算了
//如,当算4,2,3时,2,1,3已经计算了,可以将1处当做高度为2和前面的2已经组成了平地
// 计算2,1,3后,下一次循环的2(指处于这个位置的值)如果大于3(指处于这个位置的值),
// 那么3会存入栈,如果小于那么平地底部的高度正好为2
he=Math.min(height[i],height[left])-bottom;
ans+=len*he;
}
stack.push(i);
}
return ans;
}
}