- Question
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.
思路
对第一个不为0 的柱子,记录下它的位置t1, 遍历它之后的柱子(用 h 保存它之后的柱子的最高高度,记录相应位置t2), 遇到比t1柱子高的柱子或者遍历完数组停止。 h=min(t1,t2), 再从t1遍历到t2, 这样这可以找到t1与t2围成的最大容积。
重复这一过程,可以计算出所有的容积。该方法时间复杂度 O(n2) 。代码如下:
class Solution {
public:
int trap(vector<int>& height) {
int ret=0;
for(auto it=height.begin(); it!=height.end(); ){
if(*it==0) ++it;
else{
//找到第一个不为0的柱子t1
decltype(it) it2=it, end_it;
int temp=*it;
int h=0;
++it2;
//遍历t1之后的柱子,找到其后第一个高度大于t1的柱子,若没有,则找到后面最高的柱子t2
while(it2 !=height.end()){
if(*it2>=h){
h=*it2;
end_it=it2;
}
if(*it2>temp) break;
++it2;
}
if(h==0 && it2==height.end()) break;
h=min(h, temp);
while(it!=end_it){
if(*it<h) ret+=(h-*it);
++it;
}
}
}
return ret;
}
};
- 下面是我在讨论区发现一个非常棒的解法,只需要维护目前的最高水位, 不断抛弃最左或者最右的低的柱子。 该方法只需要遍历一遍数组,时间复杂度 O(n) .
class Solution {
public:
int trap(vector<int>& height) {
if(height.empty()) return 0;
auto left=height.begin(),right=height.end()-1;
int level=0, water=0, lower=0;
while(left<right){
//找到较低的柱子
lower=*left<*right? *left++:*right--;
if(level<lower) level=lower; //维护最高水位
else
water+=level-lower; //可以容纳的水量
}
return water;
}
};