1. 程式人生 > 其它 >leetcdoe 42. 接雨水 (雙指標 單調棧)

leetcdoe 42. 接雨水 (雙指標 單調棧)

連結:https://leetcode-cn.com/problems/trapping-rain-water/

題目

給定n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。

用例

示例 1:

輸入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
輸出:6
解釋:上面是由陣列 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。
示例 2:

輸入:height = [4,2,0,3,2,5]
輸出:9

提示:

n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105

思路

通過雙指標來解決接雨水問題,一個指標指向左側邊界,另一指標指向右側邊界,並設定兩個值分別記錄左側和右側高度的最大值。判斷左右最高點值哪個小,在靠近小高度的那側作積水計算

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

使用單調棧也可以實現
使用單調棧
單調遞減棧
理解題目注意題目的性質,當後面的柱子高度比前面的低時,是無法接雨水的
當找到一根比前面高的柱子,就可以計算接到的雨水
所以使用單調遞減棧
對更低的柱子入棧
更低的柱子以為這後面如果能找到高柱子,這裡就能接到雨水,所以入棧把它儲存起來
平地相當於高度 0 的柱子,沒有什麼特別影響
當出現高於棧頂的柱子時
41. 說明可以對前面的柱子結算了
42. 計算已經到手的雨水,然後出棧前面更低的柱子

計算雨水的時候需要注意的是

雨水區域的右邊 r 指的自然是當前索引 i
底部是棧頂 st.top() ,因為遇到了更高的右邊,所以它即將出棧,使用 cur 來記錄它,並讓它出棧
左邊 l 就是新的棧頂 st.top()
雨水的區域全部確定了,水坑的高度就是左右兩邊更低的一邊減去底部,寬度是在左右中間
使用乘法即可計算面積

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