LeetCode 42. Trapping Rain Water

首先说说最初的但是不正确的思路,stk存值,初始化为输入数组的第一位。从左往右读入数组每一位,如果height[i]>stk.top(),说明stk.top()无法蓄水,pop掉,替换为height[i];如果height[i]<=stk.top(),那么从i开始遍历,直到找到大于等于stk.top()的height[i]或者直到最后一位,找的时候维护变量tmp存蓄水的量,但是如果没有找到大于等于stk.top()的height[i]的话,实际上是无法蓄水的,也就是tmp是无意义的(因此要另开变量tmp而不是直接加给res),这种情况下stk要pop,然后push进原top值的下一个高度,所以还要开一个变量top_pos,存放stk.top()在数组中的位置;如果能够找到大于等于stk.top()的height[i]的话,res+=tmp,stk要pop,push进当前大于等于stk.top()的height[i]。

其实不用开stack,stk应该全程只有一个数据,因为看到tag是stack所以开了一个,实际上int变量即可。

 1 class Solution {
 2 public:
 3     int trap(vector<int>& height) {
 4         int size = height.size();
 5         if(size == 0) return 0;
 6         int i = 0, top_pos = 0;
 7         int res = 0;
 8         stack<int> stk;
 9         stk.push(height[i++]);
10         for(; i < size; ++i){
11             if(height[i] > stk.top()){
12                 stk.pop();
13                 stk.push(height[i]);
14                 top_pos = i;
15             }
16             else{
17                 int tmp = 0;
18                 while(i <= size - 1 && height[i] < stk.top()){
19                     tmp += stk.top() - height[i];
20                     ++i;
21                 }
22                 if(i == size) i = size - 1;
23                 if(height[i] < stk.top()){
24                     stk.pop();
25                     i = ++top_pos;
26                     stk.push(height[i]);
27                 }
28                 else{
29                     res += tmp;
30                     stk.pop();
31                     stk.push(height[i]);
32                     top_pos = i;
33                 }
34             }
35         }
36         return res;
37     }
38 };

这种算法140/315 test cases passed.

Input:[4,2,3]
Output:0
Expected:1
 
 
看了别人的算法,不用stack纯逻辑解决,说明一下。
water的加部分:从左向右遍历,water+=之前highest存目前最大值(不包括height[i]),也即只考虑当前高度和这之前最高高度之间的蓄水量。
water的减部分:从右向左遍历,water-=之前highest存目前最大值(包括height[i]),如果目前最大值<总体最大值,说明目前的高度在最高高度的右边,有一部分水无法蓄住,这部分无法蓄住的水量为总体最大值-目前最大值;如果目前最大值>=总体最大值,说明目前的高度在最高高度的左边或是就是最高高度,而在加部分中,蓄水量只和该高度左边的最大值有关,因此之前加的蓄水量是合理的,就不需要减去什么了。
 1 class Solution {
 2 public:
 3 int trap(vector<int>& height) {
 4     int sz=height.size(), highest=0, water=0;
 5     //from left to right, only consider the trap's left elevation
 6     for(int i=0; i<sz; i++){
 7         if(height[i]<highest) water+=highest-height[i];
 8         highest=max(highest, height[i]);
 9     }
10 
11     int prehighest=highest;
12     highest=0;
13     //from right to left, only consider the trap's right elevation, subtract the surplus water
14     for(int i=sz-1; i>=0; i--){
15         highest=max(height[i], highest);
16         if(highest<prehighest) water-=prehighest-highest;
17     }
18     return water;
19 }
20 };

 

 

以下是用deque的算法,两头进出,其实也可转换为stack,思路相同。

注意能够蓄水的条件是有凹陷,也就是一端的高度大于等于另一端高度,两端之间的高度小于它们两者,也即栈底为某一高度,当之后的高度都比它小时,就push进去,如果大于等于它,就可以形成凹陷,一直pop,计算水量。

注意可能出现一个高度之后的高度都小于它的情况,但是仍可能存在凹陷,因此将高度全部读入后还要检测deque是否为空,不为空的话就表明这种情况发生了,解决方法很简单,把deque里的数据pop_back进另一个deque,这样一来最高的高度变成了最末尾的一个,就可以形成常规凹陷,和之前判断凹陷的方法一样。这种操作执行一次即可。

 1 class Solution {
 2 public:
 3     int trap(vector<int>& height) {
 4         int n = height.size();
 5     // cin>>n;
 6     // int * height = new int[n + 10];
 7     deque<int> q;
 8     int water = 0;
 9     int maxH = 0;
10     for(int i = 0; i < n; ++i){
11         int cur = height[i];
12 
13         if(q.empty()) {q.push_back(cur);maxH = cur;}
14         else{
15             if(cur < maxH) q.push_back(cur);
16             else if(cur >= maxH){
17                 while(!q.empty()){
18                     water += maxH - q.back();
19                     q.pop_back();
20                 }
21                 maxH = cur;
22                 q.push_back(cur);
23             }
24             else continue;
25         }
26 
27             
28     }
29     if(!q.empty()){
30         deque<int> tmp;
31         while(!q.empty()){
32             int cur = q.back();
33             if(tmp.empty()) {tmp.push_back(cur); maxH = cur;}
34             else{
35                 if(cur < maxH) tmp.push_back(cur);
36                 else if(cur >= maxH){
37                     while(!tmp.empty()){
38                         water += maxH - tmp.back();
39                         tmp.pop_back();
40                     }
41                     maxH = cur;
42                     tmp.push_back(cur);
43                 }
44             }
45             q.pop_back();
46         }
47     }
48         return water;
49     }
50 };

 

 

posted @ 2016-04-04 23:46  co0oder  阅读(136)  评论(0编辑  收藏  举报