Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1]
, return 6
.
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
这道题想了蛮长时间,受到了Tags里two points的启发。思路是这样的:
首先,进行预处理,去掉两侧不能储水的部分
然后,总左向右遍历,每当V字形储水结构的右边比左边高的时候,就计算一次当前V能储存多少水,因为当V字形右边比左边高的时候不会受到后面的影响,直到结束,记下已计算的最右边的节点序号。
再次,从右向左遍历到上述节点序号,每当V字形储水结构的左边比右边高的时候,就计算一次能存储多少水,因为此时不会受到左边的影响。完毕。代码如下:
public class Solution {
public int trap(int[] height) {
int start = 0;
int end = 0;
int len = height.length;
if(len < 3)
return 0;
for(int i = 1; i < len ; i++){
if(height[i] >= height[i-1]){
continue;
}else{
start = i-1;
break;
}
}
for(int i = len-2; i >= 0; i--){
if(height[i] >= height[i+1]){
continue;
}else{
end = i+1;
break;
}
}
int leftHeight = height[start];
int rightHeight = height[end];
int leftNum = start;
int rightNum = end;
int sum = 0;
for(int i = start+1; i <= end; i++){
if(height[i] < height[leftNum]){
continue;
}else{
sum += calEach(height, leftHeight, height[i], leftNum, i);
leftNum = i;
leftHeight = height[i];
}
}
for(int i = end-1; i >= leftNum; i--){
if(height[i] < height[rightNum]){
continue;
}else{
sum += calEach(height, height[i], rightHeight, i, rightNum);
rightNum = i;
rightHeight = height[i];
}
}
return sum;
}
private int calEach(int[] height, int leftHeight, int rightHeight, int leftNum, int rightNum){
int shorter = leftHeight < rightHeight ? leftHeight : rightHeight;
int sum = 0;
for(int i = leftNum ; i <= rightNum; i++){
if(height[i] < shorter){
sum += (shorter - height[i]);
}
}
return sum;
}
}