42. Trapping Rain Water
Given n non-negative integers representing anelevation map where the width of each bar is 1, compute how much water it isable to trap after raining.
For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1]
,return 6
给定n个非负数,然后返回它们能积水多少个单位。看下图就很容易理解。
算法思想
两个柱子之间要能积水必须满足条件:两个柱子距离要大于等于1,并且它们之间只能存在比它们小的柱子。
知道了这个条件之后,考虑将问题分割,只需要找到两个柱子驻水,就可以递归求解其他的柱子,然后把每两个的柱子的水加起来就能得到总的体积。
步骤
1. 从数组头开始遍历,找到第一个有高度的柱子,当前位置就是这个柱子的下标。
2. 从当前位置开始向后查找,当前柱子高度为h,查找的时候记录下已经过的柱子的体积s1,并记录当前走过的宽度w:
a) 若可以找到一个比自己高或者和自己一样的柱子,停止,计算当前柱子到查找到的柱子之间的积水体积。s = h * w – s0。
b) 若找不到比当前位置高的柱子,就找到当前位置之后第二高的柱子,停止,计算他们之间的积水: s = h * w – s0
3. 当前位置设置为第2步找到的下一个位置,重复第2步,当前位置到达最后一个柱子。
class Solution {
public:
struct node{
int max_h;
int width;
int tmp;
int index;
};
int trap(vector<int>& a) {
node t;
if(a.size() < 1)return 0;
int sum , i , j;
int endindex = a.size() - 1;
i = j = sum = 0;
while(a[i] == 0) ++i;
while( i != endindex){
int h = a[i]; // heigth
int w = 0; // width
int temp = 0; // temp sum
t.max_h = -1;
j = i + 1;
if(j >= endindex)return sum;
while(a[j] < h){//找到下一个柱子
if(a[j] > t.max_h){//to find the second h
t.max_h = a[j];
t.width = w;
t.tmp = temp;
t.index = j;
}
temp += a[j];
j++; w++;
if( j > endindex) break;
}//while (j)
if(j <= endindex){
sum+= h * w - temp;
i = j;
}// if j <= end
else{
sum+= t.max_h * t.width - t.tmp;
i = t.index;
}//if j > end
}//while(i)
return sum;
}
};