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.
经典的接雨水问题
方法一:
第 i 块区域积水面积 = Min( Max(h[0…i]) , Max(h[i…n]) ) - h[i]
时间复杂度:O(n^2)
空间复杂度:O(n)
class Solution {
public int trap(int[] height) {
int length = height.length;
if(length <= 2)
return 0;
int[] sum = new int[length];
int result = 0;
sum[0] = 0;
sum[length - 1] = 0;
for(int i = 1;i < length - 1;i++){
int leftH = getMax(height,0,i);
int rightH = getMax(height,i,length - 1);
sum[i] = Math.min(leftH,rightH) - height[i];
}
for(int s : sum){
result += s;
}
return result;
}
public int getMax(int[] height,int start,int end){
int max = Integer.MIN_VALUE;
for(int i = start;i <= end;i++){
if(height[i] > max){
max = height[i];
}
}
return max;
}
}
方法二:
通过dp优化方法一,减少查找左右最高点的次数
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public int trap(int[] height) {
int length = height.length;
if(length < 3)
return 0;
int[] left = new int[length];
left[0] = height[0];
int[] right = new int[length];
right[length - 1] = height[length - 1];
int[] sum = new int[length];
sum[0] = 0;
sum[length - 1] = 0;
int result = 0;
for(int i = 1;i < length;i++){
left[i] = Math.max(left[i - 1],height[i]);
}
for(int j = length - 2;j >= 0;j--){
right[j] = Math.max(right[j + 1],height[j]);
}
for(int k = 1;k < length - 1;k++){
result += Math.min(left[k],right[k]) - height[k];
}
return result;
}
}
方法三:使用双指针,左右指针分别记录左,右当前的最大值。
因为i 到 j 之间,某一区域k可以接的雨水只与左右板最小值和k区域自身高度有关
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public int trap(int[] height) {
int length = height.length;
if(length < 3){
return 0;
}
int start = 0;
int end = length - 1;
int result = 0;
int max_l = height[0];
int max_r = height[length - 1];
while(start < end){
if(max_l < max_r){
result += max_l - height[start];
max_l = Math.max(max_l,height[++start]);
}else{
result += max_r - height[end];
max_r = Math.max(max_r,height[--end]);
}
}
return result;
}
}