Trapping Rain Water
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.
Solution1
- 扫描两遍数组,第一遍从左到右扫描,记录扫到当前位置的左边最大值。第二遍从右边扫描到左边,记录扫到当前位置的右边最大值,并将这二者最大值的最小值记录在一个新的数组里,那么所储存的水量便是该最小值减去当前的高度。代码如下:
public class Solution {
public int trap(int[] height) {
int[] max = new int[height.length];
int result = 0;
for(int i=0,highest=0;i<height.length;i++){//从左到右扫
highest = Math.max(highest,height[i]);//记录左边最大值
max[i] = highest;
}
for(int i=height.length-1,highest=0;i>=0;i--){//从右到左
highest = Math.max(highest,height[i]);//记录右边最大值
max[i] = Math.min(highest,max[i]);//两边最大值的最小值
result += max[i] - height[i];//两边最大值的最小值减去当前高度便是储存水量
}
return result;
}
}
Solution2
- 解法一简单易懂,但是缺点在于需要O(N)的空间复杂度,并且需要扫描两遍数组。实际上可以将两边扫面数组放在一次扫描当中实现,但是需要两个指针,每次移动较短边,因为是较短边决定了两条边中间所能够储存的水量。
public class Solution {
public int trap(int[] height) {
int result = 0;
for(int i=0,j=height.length-1,left=0,right=0;i<j;){
if(height[i]<height[j]){
left = Math.max(left,height[i]);//记录左边的最大值
result += left - height[i++];
}else{
right = Math.max(right,height[j]);
result += right - height[j--];
}
}
return result;
}
}
Solution3
- 将解法二用更简洁的语言表示如下(理解起来稍困难,可以对应着题目当中的图来一步一步理解):
public class Solution {
public int trap(int[] height) {
int result = 0;
for(int i=0,j=height.length-1,max=0;i<j;){
max = Math.max(max,height[i]<height[j]?height[i++]:height[j--]);
result += max - Math.min(max,Math.min(height[i],height[j]));
}
return result;
}
}