zoukankan      html  css  js  c++  java
  • Maximal Rectangle

    Date:

      Nov. 8, 2017.

    Problem:

      https://leetcode.com/problems/maximal-rectangle/description/

    Description:

      Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.

      For example, given the following matrix:

        1 0 1 0 0

        1 0 1 1 1

        1 1 1 1 1

        1 0 0 1 0

      Return 6.

      容易分解出子问题:http://www.cnblogs.com/neopolitan/p/7783405.html。

      用heights列表记录矩阵某一行所有节点的高度,维护它。用子问题的函数求解即可。

      这个算法的复杂度为O(N^2)。以下为submission。

     1 class Solution:
     2     def maximalRectangle(self, matrix):
     3         if len(matrix) == 0:
     4             return 0
     5         col = len(matrix[0])
     6         heights = [0 for i in range(col)]
     7         res = 0
     8         for i in matrix:
     9             for j in range(col):
    10                 if i[j] == '1':
    11                     heights[j] += 1
    12                 else:
    13                     heights[j] = 0
    14             res = max(res, self.largestRectangleArea(heights))
    15         return res
    16     def largestRectangleArea(self, heights):
    17         stack = [-1]
    18         rank = 0
    19         result = 0
    20         heights.append(0)
    21         length = len(heights)
    22         for i in range(length):
    23             while rank > 0 and heights[i] <= heights[stack[rank]]:
    24                 result = max(result, heights[stack[rank]] * (i - stack[rank - 1] - 1))
    25                 stack.pop()
    26                 rank -= 1
    27             rank += 1
    28             stack.append(i)
    29         return result

      Alter:优雅的DP解法。

      考虑逐行分析每一点所在的可能的最大矩形,每次扫描使图的当前状态增加一行。

      假设我们现在在分析某一行,这时我们能从上一行继承某些信息来简化计算,例如,上一行的同一列的点可取得的最大高度。

      于是想象正在分析的这点向上取到最大高度,然后向左右取到最大宽度,获得这样一个可能的最大矩形。

      可以证明,这种方法不一定能取到某一点所在的最大矩形,但能取尽当前状态下所有可能的最大矩形。

      对于一个可能的最大矩形来说,它的四条边之外一定紧邻着至少一个0或者矩阵边界(考虑到我们是逐行扫描,它的底边一定紧邻着矩阵边界)。假设有一个最大矩形没有被我们取到,考虑它的顶边,当顶边外紧邻着一个0时,我们对这一列应用上面的方法,显然会取到这个最大矩形;当顶边紧邻着矩阵边界时,我们对矩形底边上的任意一点应用上面的方法,显然都会取到这个矩形。因此我们总是能取得当前状态下所有可能的最大矩形。

      于是我们维护三个数组,left,height和right。

      left记录按这一方法向左能取到的最大边界,它初始化为0。它可能直接向左取到最左边界,也可能继承上一行同一列的height,这取决于它所在的宽度能不能“装得下”之前宽度的矩形。归结起来,我们这样维护left:我们用一个current_left来记录当前可取的最左边界。当分析一点matrix[i, j]时,若matrix[i, j]为0,更新current_left为j;若matrix[i, j]不为0,我们对它进行取可能最大矩形的操作。left[j] = max(left[j], current _left)。

      right依葫芦画瓢。

      height记录按这一方法向上取到的最大边界。它的维护与上一种解法相似。遇0初始化为0,否则加1。

      扫描和维护的同时,我们维护一个maxrec来记录取得矩形的最大面积。

      这种算法的复杂度为O(N^2)。优雅度为O(N!)(

      以下是submission。

     1 class Solution:
     2     def maximalRectangle(self, matrix):
     3         if len(matrix) == 0:
     4             return 0
     5         col = len(matrix[0])
     6         height = [0 for i in range(col)]
     7         left = [0 for i in range(col)]
     8         right = [col for i in range(col)]
     9         res = 0
    10         for i in matrix:
    11             current_left = 0
    12             current_right = col
    13             for j in range(col):
    14                 if i[j] == '0':
    15                     height[j] = 0
    16                     left[j] = 0
    17                     current_left = j + 1
    18                 else:
    19                     height[j] += 1
    20                     left[j] = max(left[j], current_left)
    21             for j in range(col - 1, -1, -1):
    22                 if i[j] == '0':
    23                     right[j] = col
    24                     current_right = j
    25                 else:
    26                     right[j] = min(right[j], current_right)
    27                     res = max(res, (right[j] - left[j]) * height[j])
    28         return res
  • 相关阅读:
    css 分类+选择器
    emmet语法
    程序员能力矩阵
    时间管理

    java 内存 解析
    SQL 查询优化
    2016 书单计划
    ssh框架;
    Mybatis;
  • 原文地址:https://www.cnblogs.com/neopolitan/p/7806249.html
Copyright © 2011-2022 走看看