- Trapping Rain Water My Submissions QuestionEditorial Solution
Total Accepted: 66869 Total Submissions: 206382 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!
题意:给定一个序列,为柱子的高度,计算中间
可蓄水量
这是一个难题,这里来说说基本思路:
从上图可以看出,每段可以蓄水的区间两端的高度都是这个局部区间的最高和
次高值(或者等高),关键是找到一中可行的方式来划分相同子问题。
1.对于总区间,找到最高值和次高值包含的区间,计算中间蓄水量
2.对于除中间之外的两端区间,转化为相同子问题求解。
对于1中找最高值和次高值有很多方法,这里通过左右夹逼的方式来求,
左右比较冒泡出最优值,同时在比较过程存储了次优值
class Solution {
public:
int trap(vector<int>& height) {
int n= height.size();
if(n<3)return 0; //递归出口
else if(n==3){
if(height[1]<height[0]&&height[1]<height[2]) //三个柱子可计算容水量
return min(height[2]-height[1],height[0]-height[1]);
else return 0;
}
else{
int left=0,right=n-1;
int max1=-1,max2=-1,id1,id2;
while(left<right){ //依次从两端向中间靠拢,寻找两端的最高处
if(height[left]>=max1){ //保留左半部局部最高点
max1 = height[left];
id1 = left;
}
if(height[right]>=max2){ //保留右半部局部最高点
max2 = height[right];
id2 = right;
}
if(height[left]<height[right])++left; //哪边小哪边向中间靠拢
else --right;
}
int sum=0;
for(int i=id1+1;i<id2;++i) //计算中间包含高度和
sum+=height[i];
sum = (id2-id1-1)*min(height[id1],height[id2])-sum;//得到中间容水量
vector<int> fir,sec;
auto it_beg = height.begin(),it_end=height.end();
fir.assign(it_beg,it_beg+id1+1);
sec.assign(it_beg+id2,it_end);
return trap(fir)+sum+trap(sec); //左半部容水+中间容水+右半部容水
}
}
};