Leetcode 85. 最大矩形 maximal rectangle

題目連接
這個題目是 84 題的升級版
84 題題解python

暴力

暴力,能過(可是 84 題用相似的策略是不行的)segmentfault

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        n = len(matrix)
        if n == 0: return 0
        m = len(matrix[0])
        max_l = [[0] * m for i in range(n)]
        for i in range(n):
            cur = 0
            for j in range(m):
                if matrix[i][j] == '1':
                    cur += 1
                else:
                    cur = 0
                max_l[i][j] = cur
        ans = 0
        for i in range(n):
            for j in range(m):
                if matrix[i][j] == '1':
                    minl = max_l[i][j]
                    for k in range(i, n):
                        if matrix[k][j] == '0': break
                        minl = min(minl, max_l[k][j])
                        ans = max(ans, minl * (k-i+1))
        return ans

max_l 是每一個點向左延伸最多有多少個格子。app

計算 max_l 矩陣要遍歷 n × m。函數

而後再從每一個點開始,看這個點做爲右上頂點的矩形的最大面積,這個又須要沿着 n 方向遍歷。code

因此時間複雜度是 O(n^2 × m)leetcode

轉換爲多個 84 題的問題,對每一行使用遞增棧方法

上面的方法 max_l 的每一列都至關於 84 題中的一個問題。
下面的代碼直接拿來了 84 題的代碼,對每一行調用了那個函數。get

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        hs = [0] + heights + [0]
        s = []
        ans = 0
        for i, h in enumerate(hs):
            while s and hs[s[-1]] > h:
                j = s.pop()
                ans = max(ans, hs[j] * (i-s[-1]-1))
            s.append(i)
        return ans

    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        n = len(matrix)
        if n == 0: return 0
        m = len(matrix[0])
        dp = [int(i) for i in matrix[0]]
        ans = self.largestRectangleArea(dp)
        for i in range(1, n):
            for j in range(m):
                if matrix[i][j] == '1':
                    dp[j] += 1
                else:
                    dp[j] = 0
            ans = max(ans, self.largestRectangleArea(dp))
        return ans

動態規劃

從每一個爲 1 的位置,咱們能夠計算當前位置上這樣的矩形的面積:博客

  1. 高度儘可能往上延伸(到上面第一個 0 或者邊界)
  2. 左右儘可能寬

那麼全局最大的面積必定在這裏面。io

任意一點都有一個 h 高度,l 左邊界,r 右邊界。矩形面積是 h × (r - l)則裏的 l 是該點左邊第一個 0 (或邊界)的右邊一個元素的下標。r 是最右邊的一個 0 或者(邊界)下標。class

這裏 h 好計算,當前是 0,h 設爲 0,不是 0 則 h 是上一行的 h 加一。

l 和 r,以 l 爲例,始終維護當前左邊界,(初始爲 0)若是當前是 1,l 是當前左邊界和上一行左邊界的最大值(由於咱們要看整個左邊界的狀況);若是當前是 0,就更新當前左邊界爲當前下標加一,l 設爲 0。(這裏設爲 0 起始並非真的 0,並且對本行該位置計算不起做用(由於當前位置 h 確定爲 0,一乘就是 0 了)主要是至關於重置了狀態,下一行的左邊界就不受本行限制了。

r 的狀況相似。

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        n = len(matrix)
        if n == 0: return 0
        m = len(matrix[0])
        l = [0] * m
        r = [m] * m
        h = [0] * m
        ans = 0
        for i in range(n):
            for j in range(m):
                if matrix[i][j] == '1': 
                    h[j] += 1
                else: 
                    h[j] = 0
            cur = 0
            for j in range(m):
                if matrix[i][j] == '1': 
                    l[j] = max(cur, l[j])
                else:
                    cur = j + 1
                    l[j] = 0
            cur = m
            for j in range(m-1, -1, -1):
                if matrix[i][j] == '1':
                    r[j] = min(cur, r[j])
                else:
                    r[j] = m
                    cur = j
            for j in range(m):
                ans = max(ans, h[j] * (r[j] - l[j]))
        return ans

歡迎來個人博客: https://codeplot.top/
個人博客刷題分類:https://codeplot.top/categories/%E5%88%B7%E9%A2%98/

相關文章
相關標籤/搜索