以 下 题 目 网 址 来 源 https://leetcode.com/
42. Trapping Rain Water
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
.
- Total Accepted: 100558
- Total Submissions: 281963
- Difficulty: Hard
- Contributors: Admin
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),这里分为两种情况,第一种是左锋已经是最高峰,所以右峰需要是低于左锋的最高峰,为了方便计算,当有多个等高的右峰时,取最右边的;第二种是左锋不是最高峰,所以在找右峰的同时需要保证右峰的海拔刚好大于等于左锋,在往右遍历其他山峰时若找到第一个大于左锋的山峰就停止。找到右峰后计算两峰之间的最大容积在扣去中间夹杂的小山峰,便得到一个山谷的积水容积,然后将前一个山谷的右峰作为左锋,继续寻找左锋。以此类推,直到找不到右峰为止,即右峰的值为默认值(right==0)。
代码如下:
int trap(vector<int>& height) {
int i=0;
if( height.empty() ) return 0;
while( height[i]==0 ) i++;
int left,right,sum=0;
for(int j=i; j<height.size();){
int s=1;
left=j,right=0;
if( height[j+1] >= height[j] ) ;
else{
int wide=1,h=0;
int temp=height[j+1];
for(int k=j+1; k<height.size(); k++){
if( height[k] >= temp ){
temp=height[k];
right=k;
if( height[k] > height[left] ) break;
}
}
if( right==0 ) break;
wide=right-left-1;
h=height[left] <= height[right] ? height[left] : height[right] ;
int bar=0;
for(int r=left+1; r<right; r++){
bar+=height[r];
}
sum+=h*wide-bar;
s=wide+1;
// cout<<"left= "<<left <<endl;
// cout<<"right= "<<right <<endl;
// cout<<"wide= "<<wide <<endl;
// cout<<"h= "<<h <<endl;
// cout<<"bar= "<<bar <<endl;
// cout<<"sum= "<<sum <<endl;
// cout<<endl;
}
j+=s;
}
return sum;
}