题目链接:https://leetcode.com/problems/trapping-rain-water/
方法一:双指针
官方最优解 8ms 99%:
思路就是保存一个左指针left,右指针right。以及左指针遍历的最大值以及右指针遍历的最大值,
当array[left]比较小时进入左侧的最大值更换以及面积计算,
反之进入右侧计算。这样的目的是保证每一步计算的面积都是有效的,不会悬空。
一个极端的例子,比如遇到了array[left]是全数组最大值,那么一直更新右侧的最大值,
然后一个从右向左的顺序保证了每一次 maxR-array[right]的值都是有效的。
class Solution {
public int trap(int[] height) {
if(height==null||height.length==0)
return 0;
int left=0,right=height.length-1;
int maxL=0,maxR=0,ans=0;
while(left<right){
if(height[left]<height[right]){
maxL=Math.max(maxL,height[left]);
ans+=(maxL-height[left]);
left++;
}else{
maxR=Math.max(maxR,height[right]);
ans+=(maxR-height[right]);
right--;
}
}
return ans;
}
}
时间复杂度O(n) 空间复杂度O(1)。
方法二:DP
官方写的名字叫DP,不过我感觉更像初中数学里求阴影部分面积一样,先是从左到右找最大值分别保存在
一个数组left里,然后同理从右向左保存最大值到right数组里,最后迭代一遍,找两者(left,right)的最小值
减去原有的height[ i ],就是当前迭代可以加上的有效面积。
看个示意图更好理解:
AC 8ms 99% 时间复杂度O(n),空间O(n)。
class Solution {
public int trap(int[] height) {
if(height==null||height.length==0)
return 0;
int[] left=new int[height.length];
int[] right=new int[height.length];
int ans=0;
left[0]=height[0];
for(int i=1;i<height.length;i++){
left[i]=Math.max(height[i],left[i-1]);
}
right[height.length-1]=height[height.length-1];
for(int i=height.length-2;i>=0;i--){
right[i]=Math.max(height[i],right[i+1]);
}
for(int i=0;i<height.length;i++){
ans+=(Math.min(left[i],right[i])-height[i]);
}
return ans;
}
}