[LeeCode题解 Hard]最大矩形

最大矩形


    题目描述   

           给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。


    输入样例

[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]

    

   输出样例

6

    

   解题思路

        这道题涉及一个经典的问题:求矩阵的最大子矩阵,是典型的动态规划问题

扫描二维码关注公众号,回复: 52020 查看本文章

        首先应该看如何简化求解的过程,这道题的主要思路就是:对于矩阵中的每一个点,他的最大面积即是最大高度乘以该高度下延伸的最大宽度(其实这样对于每个矩阵的点的最大面积并不一定是对的,但是要这样子想,即使这一个点上的最大面积并不是在最大高度下延伸的宽度的面积。但是在同一行中,如果满足上述条件,必定有高度没有这么高的点,那在这些点里面,必定有一点可以求得刚才的面积存在,所以可以求出刚才那一个点的最大面积,最后的结果因而是正确的)

         掌握了基本原理之后我们可以下递归原理:

         首先最大高度很好理解,如果该点为0,那么该点的最大高度为0,如果非0,即为上一行最大高度加1,即

max_height[j] = max_height[j] + 1

          其次是左/右端点,我们只需要找一个变量记录本行该点的左/右边界即可,但是还要满足在最大高度下的最大延伸,所以还要取上一行该点边界的较大/小值。故若该点为0,重置边界值,重设该点的左/右边界,否则,取上述值。               

while j >= 0:
                if matrix[i][j] == "1":
                    max_right[j] = min(max_right[j], right_border)
                else:
                    right_border = j - 1
                    max_right[j] = n - 1
                j = j - 1

          接下来就比较简单了,求出最大面积即可。


    代码展示

class Solution:
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        m = len(matrix)
        n = 0
        if m > 0:
            n = len(matrix[0])
        max_height = [0 for i in range(0, n)]
        max_right = [n - 1 for i in range(0, n)]
        max_left = [0 for i in range(0, n)]
        max_area = 0

        for i in range(0, m):
            left_border = 0
            right_border = n - 1

            for j in range(0, n):
                if matrix[i][j] == "1":
                    max_height[j] = max_height[j] + 1
                    max_left[j] = max(max_left[j], left_border)
                else:
                    max_height[j] = 0
                    left_border = j + 1
                    max_left[j] = 0

            j = n - 1
            while j >= 0:
                if matrix[i][j] == "1":
                    max_right[j] = min(max_right[j], right_border)
                else:
                    right_border = j - 1
                    max_right[j] = n - 1
                j = j - 1

            for j in range(0, n):
                if (max_right[j] - max_left[j] + 1) * max_height[j] > max_area:
                    max_area = (max_right[j] - max_left[j] + 1) * max_height[j]

        return max_area

猜你喜欢

转载自blog.csdn.net/weixin_37743125/article/details/80055323