1. 程式人生 > 實用技巧 >棧-最大面積問題

棧-最大面積問題

84. 柱狀圖中最大的矩形
給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度為 1 。
求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。

示例:
輸入: [2,1,5,6,2,3]
輸出: 10


我們首先從左往右對陣列進行遍歷,藉助單調棧求出了每根柱子的左邊界,隨後從右往左對陣列進行遍歷,藉助單調棧求出了每根柱子的右邊界。
class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        n = len(heights)
        left, right 
= [0] * n, [0] * n mono_stack = list() for i in range(n): while mono_stack and heights[mono_stack[-1]] >= heights[i]: mono_stack.pop() left[i] = mono_stack[-1] if mono_stack else -1 mono_stack.append(i) mono_stack
= list() for i in range(n - 1, -1, -1): while mono_stack and heights[mono_stack[-1]] >= heights[i]: mono_stack.pop() right[i] = mono_stack[-1] if mono_stack else n mono_stack.append(i) ans = max((right[i] - left[i] - 1) * heights[i] for
i in range(n)) if n > 0 else 0 return ans 優化:解決右邊界優化問題 class Solution: def largestRectangleArea(self, heights: List[int]) -> int: n = len(heights) left, right = [0] * n, [n] * n mono_stack = list() for i in range(n): while mono_stack and heights[mono_stack[-1]] >= heights[i]: right[mono_stack[-1]] = i mono_stack.pop() left[i] = mono_stack[-1] if mono_stack else -1 mono_stack.append(i) ans = max((right[i] - left[i] - 1) * heights[i] for i in range(n)) if n > 0 else 0 return ans
42. 接雨水
給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。
上面是由陣列 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。 感謝 Marcos 貢獻此圖。
示例:

輸入: [0,1,0,2,1,0,1,3,2,1,2,1]
輸出: 6

class Solution(object):
    def trap(self, height):
        n = len(height)
        # 同時從左往右和從右往左計算有效面積
        s1, s2 = 0, 0
        max1, max2 = 0, 0
        for i in range(n):
            if height[i] > max1:
                max1 = height[i]
            if height[n - i - 1] > max2:
                max2 = height[n - i - 1]
            s1 += max1
            s2 += max2
        # 積水面積 = S1 + S2 - 矩形面積 - 柱子面積;max1或者max2都表示最大的高度
        res = s1 + s2 - max1 * len(height) - sum(height)
        return res
85. 最大矩形
給定一個僅包含 0 和 1 的二維二進位制矩陣,找出只包含 1 的最大矩形,並返回其面積。
示例:

輸入:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
輸出: 6

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        if not matrix:
            return 0
        # 單調棧的應用 2
        def getLargestRectLayer(heights):
            ret = 0
            stack = []
            heights = [0] + heights + [0]
            for i in range(len(heights)):
                while stack and heights[stack[-1]] > heights[i]:
                    tmp = stack.pop()
                    ret = max(ret, (i - stack[-1] - 1) * heights[tmp])
                stack.append(i)
            return ret
        def getHeights(array, heights):
            for i in range(len(heights)):
                if array[i] == "1":
                    heights[i] += 1
                else:
                    heights[i]  = 0
            return heights
        # 對於每一層 獲取heights陣列即可
        ret = 0
        m = len(matrix)
        for i in range(m):
            if i == 0:
                heights = list(map(int, matrix[0]))
            else:
                heights = getHeights(matrix[i], heights)
            retLayer = getLargestRectLayer(heights)
            ret = max(ret, retLayer)
        return ret