LeetCode 42. Trapping Rain Water

解法一:DP

遇到不会的题目,先想想暴力怎么做。对于每个元素,如果用暴力做的话,分别向左向右找最大的值,那么当前元素能装的水为 min(leftmax,rightmax)-a[i]。

leftmax和rightmax都可以记录下来。以leftmax为例,leftmax[i] = max(leftmax[i-1],a[i])。这样的话,每个元素能装的水为 min(leftmax[i],rightmax[i])-a[i]。

class Solution {
public:
    int trap(vector<int>& height) {
        if (height.size()==0) return 0;
        int n=height.size();
        vector<int> leftmax(n), rightmax(n);
        
        leftmax[0] = height[0];
        for (int i=1;i<n;++i)
            leftmax[i] = max(leftmax[i-1],height[i]);
        
        rightmax[n-1] = height[n-1];
        for (int i=n-2;i>=0;--i)
            rightmax[i] = max(rightmax[i+1],height[i]);
        
        int res=0;
        for (int i=0;i<n;++i){
            res += min(leftmax[i],rightmax[i])-height[i];
        }
        return res;
    }
};

 

解法二:Two Pointers

思路还是一样的思路,但是这里用left和right两个指针来表示左和右的最大值。一开始分别指向数组的收尾位置,从两边向中间扫描,扫描方向为指向较小元素的指针向较大的指针(因为是min(leftmax,rightmax)-a[i])。如果扫描的元素比较小的指针还小,那么res+= height[小指针]-height[i];否则更新该指针,并重新判断扫描方向,直至left==right为止。

class Solution {
public:
    int trap(vector<int>& height) {
        if (height.size()==0) return 0;
        int n=height.size();
        int left=0, right=n-1;
        int leftmax=0, rightmax=0;
        int res=0;
        while (left<right){
            if (height[left]<height[right]){
                if (height[left]>leftmax) leftmax=height[left];
                else res+=leftmax-height[left];
                ++left;
            }else{
                if (height[right]>rightmax) rightmax=height[right];
                else res+=rightmax-height[right];
                --right;
            }
        }
        return res;
    }
};

  

解法三:Stack

stack是最直观的的解法,维护一个递减的单调栈,遇到比top元素小的入栈,遇到比top大的,出栈直到当前元素比top小入栈为止。出栈的元素计算一下加入到结果中。

需要注意的是,这里必须i-left-1,因为因为left,mid,i的index都不一定是连续的。

class Solution {
public:
    int trap(vector<int>& height) {
        if (height.size()==0) return 0;
        int res=0;
        stack<int> s;
        for (int i=0;i<height.size();++i){
            while (!s.empty() && height[i]>height[s.top()]){
                int mid=s.top(); s.pop();
                if (s.empty()) break;
                int left=s.top();
                res += ( min(height[i],height[left])-height[mid] ) * (i-left-1);
            }
            s.push(i);
        }
        return res;
    }
};

 

posted @ 2018-07-30 22:30  約束の空  阅读(145)  评论(0编辑  收藏  举报