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.
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!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
解法一:
收集雨水:只需要记录当前位置左侧最大值,右侧最大值,如果当前位置高度小于左侧最大值和右侧最大值的最小值,则当前位置的积水量为 这个最小值 减去 当前位置高度,否则当前位置不积水。
用vector 容器记录当前位置的最大值和最小值。
所以空间复杂度为o(2n),时间复杂度为o(3n)。
代码如下:
int trap(vector<int>& height) {
int res=0,mx=INT_MIN,n=height.size();
vector <int> maxleft(n,INT_MIN);// 一个大小为n容器,初始化为最小值,记录左侧最大值
vector <int> maxright(n,INT_MIN);// 一个大小为n容器,初始化为最小值,记录右侧最大值
for(int i=0;i<n;++i){
maxleft[i]=mx;
mx=max(mx,height[i]);
}
mx=INT_MIN;
for(int i=n-1;i>=0;--i){
maxright[i]=mx;
mx=max(mx,height[i]);
}
for(int i=1;i<n-1;++i){// 记录积水量
int minmax=min(maxleft[i],maxright[i]);
if(height[i]<minmax)res+=minmax-height[i];
}
return res;
}
解法二:
对解法一进行优化 空间复杂度o(n),时间复杂度o(2n),用一个容器。
int trap(vector<int>& height) {
int res=0,mx=INT_MIN,n=height.size();
vector <int> maxdp(n,INT_MIN);// 一个大小为n容器,初始化为最小值,记录当前位置的左侧最大值和右侧最大值的较小者
for(int i=0;i<n;++i){//现存左侧最大值
maxdp[i]=mx;
mx=max(mx,height[i]);
}
mx=INT_MIN;//此时记录右侧最大值
for(int i=n-1;i>=0;--i){
maxdp[i]=min(mx,maxdp[i]);//记录当前位置的左侧最大值和右侧最大值的较小者
mx=max(mx,height[i]);
if(height[i]<maxdp[i])res+=maxdp[i]-height[i];//记录最大积水值
}
return res;
}
解法三:
时间复杂度为O(1),空间复杂度为O(n)
int trap(vector<int>& height) {
int res=0,l=0,r=height.size()-1,lever=INT_MIN;
while(l<r){
int lower=height[height[l]<height[r]?l++:r--];//记录左边和右边较小的值,这样除了递增和边界有积水,这样记录最小值,这样不会取到最大值,只会取到较小值
lever=max(lever,lower);//记录最小值中的最大值,相当于两侧最大值的较小值。
res+=lever-lower; //记录积水量
}
return res;
}
更好理解了
int trap(vector<int>& height) {
int res=0,l=0,r=height.size()-1,leftmax=INT_MIN,rightmax=INT_MIN;
while(l<r){//双指针
if(height[l]<height[r]){//左边值小于右边值,此刻不需要知道右面最大值,只需要知道左边最大值即可
if(height[l]>=leftmax)leftmax=height[l];
else res+=leftmax-height[l];
++l;//递增
}
else{//左边值大于右边值,不需要知道左面最大值,只需要知道右面最大值
if(height[r]>=rightmax)rightmax=height[r];
else res+=rightmax-height[r];
--r;//递减
}
}
return res;
还可以用堆栈方法解决。