1. 程式人生 > 其它 >#Leetcode#Q42.接雨水 C++

#Leetcode#Q42.接雨水 C++

技術標籤:刷題leetcode演算法

Solution1: 棧

從左向右遍歷,維護一個從棧底向棧頂遞減的棧,遇到比棧頂小的入棧,遇到大的則出棧

寫的很垃圾,AC 了之後就不想改了

//棧:解法1
class Solution {
public:
    int trap(vector<int>& height) {
        int res = 0;
        stack<pair<int,int> > ht;
        ht.push(pair<int,int>(0,-1));
        for(int i=0;i<height.size();++i){
            if(height[i] < (ht.top().first))
                ht.push(pair<int,int>(height[i],i));
            else{
                while(ht.size()>1 && height[i] >= ht.top().first){
                    int bottom = ht.top().first;
                    if(height[i] == ht.top().first){
                        ht.pop();
                        break;
                    }
                    ht.pop();
                    if(ht.top().second < 0) break;
                    int width = i - ht.top().second -1;
                    res += (min(ht.top().first,height[i]) - bottom) * width;
                }
                if(height[i] < ht.top().first || (ht.size() == 1 && height[i]))
                    ht.push(pair<int,int>(height[i],i));
            }
        }
        return res;
    }
};

Solution 2:動態規劃

維護兩個陣列表示左側最高和右側最高,根據木桶理論,只有當前所處位置的高度都低於左右兩側最高的才有可能蓄水,

蓄水量=左右兩側最高中較小的高度-當前高度

class Solution {
public:
    int trap(vector<int>& height) {
        int len = height.size();
        if(len<3) return 0; 

        int res = 0;
        vector<int> maxleft(len,0);
        vector<int> maxright(len,0);

        for(int i=1;i<len;++i)
            maxleft[i] = max(maxleft[i-1],height[i-1]);
        for(int i=len-2;i>=0;i--)
            maxright[i] = max(maxright[i+1],height[i+1]);
        for(int i=1;i<len-1;++i){
            int minvalue = min(maxleft[i],maxright[i]);
            if(height[i] < minvalue) res += minvalue - height[i];
        }
        return res;
    }
};

Solution 3:動態規劃進階版本

class Solution {
public:
    int trap(vector<int>& height) {
        int len = height.size();
        if(len<3) return 0; 
        //兩個指標分別指向最左側和最右側,只有中間的比兩邊低才有可能蓄水
        int res = 0;
        int left = 1;
        int right = len-2;
        int maxleft = height[0];
        int maxright = height[len-1];
        //i只用作計數,不作為指標
        for(int i=1;i<len-1;++i){
            //兩個選更矮的那一個方向開始更新。我們需要選出左右兩側最高的矮的一方;如果左側鄰近那個小於右側鄰近那個,
            if(height[left-1] < height[right+1]){
                maxleft = max(maxleft,height[left-1]);
                if(maxleft > height[left])
                    res += maxleft - height[left];
                left++;
            }else{
                maxright = max(maxright,height[right+1]);
                if(maxright > height[right])
                    res += maxright - height[right];
                right--;
            }
        }
        return res;
    }
};