1.动态规划
可以发现当height中存在一些坑时,才可以接雨水;对Height[i],其能够接雨水意味着其左边两边必定有坑的边界,能够接多少雨水取决于坑的边界的值
对于height[i],记录其左边最大的值left[i]和右边最大的值right[i],则边界的高度为二者的最小值num=min(left[i],right[i])
height[i]能接的雨水量是num=height[i]
代码如下:
class Solution {
public:
int trap(vector<int>& height) {
int n = height.size();
// left[i]表示i左边的最大值,right[i]表示i右边的最大值
//left[i],right[i]即表示当height[i]可以接雨水时,其左右两边的高度
vector<int> left(n), right(n);
for (int i = 1; i < n; i++) {
left[i] = max(left[i - 1], height[i - 1]);
}
for (int i = n - 2; i >= 0; i--) {
right[i] = max(right[i + 1], height[i + 1]);
}
int water = 0;
for (int i = 0; i < n; i++) {
int level = min(left[i], right[i]);
water += max(0, level - height[i]);
}
return water;
}
};
2.双指针
上述方法需要o(n)的额外空间
可以通过设置left,right指针来代替两个数组,这里的关键是何时更新left,right指针
left是从左到右遍历,right是从右到左遍历,且我们知道对于元素height[i],其左边的最大值max_left=max(max_left,height[i-1]),即height[left-1]可能成为max_left,
同理,可得height[right+1]可能成为max_right
只要保证height[left-1]<height[right+1],则max_left一定小于max_right.理由如下:
因为max_left是由height[left-1]更新过来的,且height[left-1]<height[right+1],而height[right+1]会更新max_right,所以必定有max_left<max_right
反之,就从右到左
代码如下:
class Solution {
public:
int trap(vector<int>& height) {
if(height.size()==0)
return 0;
int sum=0;
int max_left=0;
int max_right=0;
int left=1;
int right=height.size()-2;
for(int i=1;i<height.size()-1;i++)
{
if(height[left-1]<height[right+1])
{
max_left=max(max_left,height[left-1]);
sum+=max(0,max_left-height[left]);
left++;
}
else
{
max_right=max(max_right,height[right+1]);
sum+=max(0,max_right-height[right]);
right--;
}
}
return sum;
}
};
3.观察法
可以发现接过雨水之后,整个数组像山字形一样,只有一个最大值,在该最大值左边数组是不严格递增,右边是不严格递减
只需要计算改变前后的差值,即是接雨水的值。
代码如下:
class Solution {
public:
int trap(vector<int>& height) {
int len=height.size();
if(len==0)
return 0;
int num=height[0];
int pos=0;
for(int i=0;i<len;i++)
{
if(height[i]>num)
{
num=height[i];
pos=i;
}
}//寻找最大值的位置
int sum=0,cur=height[0];
for(int i=1;i<pos;i++)
{
if(height[i]<cur)
sum+=cur-height[i];
else
cur=height[i];
}
cur=height[len-1];
for(int i=len-2;i>pos;i--)
{
if(height[i]<cur)
sum+=cur-height[i];
else
cur=height[i];
}
return sum;
}
};