42. Trapping Rain Water
Total Accepted: 72222 Total Submissions: 212130 Difficulty: Hard
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.
For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1]
, return 6
.
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!
【分析】
直观来看,左右两侧,能够装水的体积只与较低的一侧相关,某种意义上,我们只需要从一侧进行遍历便可以求出最大装水量。但是,无论我们从哪一侧遍历,另一侧的不确定性都会增加求取装水体积的难度,需要细分求解,因此,我们采用两侧逼近的方法更为妥当,无论中间数据为何种形态,两侧逼近都能较为简洁的求解:
具体思路:左右下标为left,right,输入数据集名为height,如果height[left]<height[right],即左侧高度低于右侧,那么,装水的量主要由左侧决定,我们移动左侧下标,如果在移动过程中,left下标对用数据大于其右侧数据,则可构成装水容器,计算装水量,并移动下标,直到left下标对应数据小于其右侧数据,我们把left移动至此,此轮循环结束,下一次继续判断height[left]与height[right]的大小,如此,直至left>=right退出,返回结果。
【解法】
class Solution {
public:
int trap(vector<int>& height)
{
int sumOfWater=0;//装水体积
int left,right;//数组左右下标
left=0;
right=height.size()-1;
while(left<right)//两侧对向移动,循环结束条件
{
if(height[left]<height[right])//左侧小于右侧
{
int cur=left;//记录当前左侧下标
while(height[left]>=height[cur]&&cur<right)//若左侧下标对应数据右侧(相邻)数据比它小,则可构成容器
{
sumOfWater+=(height[left]-height[cur]);//计算局部装水量
cur++;
}
left=cur;//<span style="font-family: FangSong_GB2312;">将左侧下标移动至从左侧遍历的第一个大于原始值的数的下标处</span>
}
else
{
int cur=right;
while(height[right]>=height[cur]&&cur>left)
{
sumOfWater+=(height[right]-height[cur]);
cur--;
}
right=cur;
}
}
return sumOfWater;
}
};