双指针法
基本思路是找每一列左边最大值Lmax和右边最大值Rmax,如果min(Lmax,Rmax)大于该列高度h,那么就可以蓄水h-min(Lmax,Rmax),否则不能蓄水。
如果维护两个数组来记录每一列的Lmax和Rmax,那就可以在O(1)时间内得到这两个值了,但是需要额外的空间。双指针法就可以优化这部分额外的空间。
用left和right标记两个指针,lmax和rmax标记left左边的最大值和right右边的最大值。height表示输入的数组。如果height[left]<height[right],那么left++,否则right–。这样就能保证在height[left]<height[right]时,left及左边的所有值都小于height[right]。再加入上述蓄水的过程。对left+1来说,left及左边的所有值都小于right对应的高度,那么left+1左边的最大高度肯定小于右边的最大高度,这样只要用left的值更新lmax,就能得到最初要求的min(Lmax,Rmax)了。
class Solution {
public:
int trap(vector<int>& height) {
int ans=0;
int lmax(0),rmax(0),left(0),right(height.size()-1);
while(left<right){
if(height[left]<height[right]){
lmax = max(lmax,height[left]);
if(lmax>height[left+1]) ans+=lmax - height[left+1];
++left;
}
else{
rmax = max(rmax,height[right]);
if(rmax>height[right-1]) ans+=rmax - height[right-1];
--right;
}
}
return ans;
}
};