LeetCode:接雨水

題目

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

在這裏插入圖片描述
上面是由數組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水

思路

  • 暴力法

每個位置i能裝的雨點數目,是由0-i1 這一段的最大值和i+1-n-1這一段的最大值,這兩邊的最大值中的較小值- height[i]得到的。因此遍歷到一個位置,就用兩個for分別尋找左右兩邊的最大值。

  • 化簡的暴力法
    我們還可以先遍歷一遍數組,統計每個每個位置i之前的最大值是多少,存到一個數組中。就是事先把每個位置左邊和右邊的最大值存下來。

  • VN法
    這個方法比較巧妙
    用兩個變量S1,S2,分別統計: 1. 從左至右 ,每個位置到開頭位置的最大值,然後加上變量上去。2. 從右到左,每個位置到結尾位置的最大值,加到變量上去。
    在這裏插入圖片描述
    在這裏插入圖片描述
    然後 S1+S2 = 總面積 + 重疊面積
    重疊面積 = 雨水面積 + sum(height)

  • 單調棧
    之前也有一道單調棧的題目, 739.每日溫度.
    什麼是單調棧。就是棧內的數據,從棧底到棧頂都是單調的。
    這道題需要構建一個遞減的單調棧。因爲假設第i個位置的height大於棧頂,說明棧頂對應的位置是可以接到雨水的,這時候就開始計算一下前一個位置能接多少水。如果棧頂元素是k,且棧頂下面的位置也是k,那這些位置都一起算雨水。
    面積爲:( i- j-1) * min(height[i], stack[j]) - k)
    cur_top是i的前一個位置。j是不等於k且離k最近的位置。

class Solution:
    def trap(self, height: List[int]) -> int:
        stack = []  # val, index
        ans = 0
        for i in range(len(height)):
            while stack and stack[-1][0] < height[i]:
                cur = stack.pop()
                while stack and stack[-1][0] == cur[0]:
                    stack.pop()
                if stack:
                    ans += (min(stack[-1][0], height[i]) - cur[0]) * (i - stack[-1][1] -1)
            stack.append([height[i], i])
        return ans
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章