Maximal Rectangle
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
以上是关于Maximal Rectangle的主要内容,如果未能解决你的问题,请参考以下文章