42. Trapping Rain Water (Array,stack; DP)

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!

思路:动态规划。第一次存储从开始到i最高的位置,求最高位置a之前的存水量=a与a之前最高位置b之间的水量+b与b之前最高位置c之间的水量...

第二次存储从末尾到i最高的位置,求最高位置a之后的存水量=a与a之前最高位置m之间的水量+m与m之前最高位置n之间的水量...

class Solution {
public:
    int trap(vector<int>& height) {
        int size = height.size();
        if(size==0) return 0;
        
        vector<int> dp(size,0); //save the highest position until now
        int ret = 0;
        int left,right;
        
        //first traverse from left to right
        for(int i = 1; i < size; i++){
            //state transfer
            if(height[i] > height[dp[i-1]]) dp[i]=i;
            else dp[i] = dp[i-1];
        }
        
        //calculate the water to the left of the highest position
        left = dp[size-1];
        while(left>0){
            right=left;
            left=dp[right-1];
            for(int i = left+1; i < right; i++){
                ret += (height[left]-height[i]);
            }
        }
  
        //second traverse from right to highest pos
        int highestPos=dp[size-1];
        dp[size-1]=size-1;
        for(int i = size-2; i >= highestPos; i--){
            //state transfer
            if(height[i] > height[dp[i+1]]) dp[i]=i;
            else dp[i] = dp[i+1];
        }
   
        //calculate the water to the right of the highest position
        right=highestPos;
        while(right<size-1){
            left=right;
            right=dp[left+1];
            for(int i = left+1; i < right; i++){
                ret += (height[right]-height[i]);
            }
        }
        
        return ret;
    }
};

 

 改进:用stack代替vector作为状态存储。stack的栈顶是到目前为止最大元素的下标,因为最高位置是关键,找到最高位置,可以往左,往右计算水位。

stack的实现类似用两个stack实现能够返回最大元素的stack。

class Solution {
public:
    int trap(vector<int>& height) {
        int size = height.size();
        if(size==0) return 0;
        
        stack<int> s;
        s.push(0);
        int i, ret = 0, highestPos;
        
        
        //First traverse from left to right
        for(int i = 0; i < size; i++){
            if(height[i]<=height[s.top()]) continue;
            
            s.push(i);
        }
        
        i=s.top();
        highestPos = i;
        while(1){
            if(i==s.top()){
                s.pop();
                if(s.empty()) break;
            }
            else{
                ret+=(height[s.top()]-height[i]);
            }
            i--;
        }
        
        //then traverse from right to left
        s.push(size-1);
        for(int i = size-2; i >= highestPos; i--){
            if(height[i]<=height[s.top()]) continue;
            
            s.push(i);
        }
        
        i=highestPos;
        while(1){
            if(i==s.top()){
                s.pop();
                if(s.empty()) break;
            }
            else{
                ret+=(height[s.top()]-height[i]);
            }
            i++;
        }
        return ret;
    }
};

 

posted on 2015-10-09 12:02  joannae  阅读(233)  评论(0编辑  收藏  举报

导航