LeetCode 85. Maximal Rectangle

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

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.

Example:

Input:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
Output: 6

Solution

Solution 1

2260 ms AC,速度比较慢。
将二维问题转化为一维求最长连续子序列的问题。对于第 i 行和第 j 行,求出 i 行到 j 行之间每一列的和,如果这个和等于 (j-i+1),(说明这一列全为 1,可以成为矩阵的一个列)将这一列标记为1,否则将这一列标记为0。然后第 i 行到第 j 列其实形成了一个只包含 0 和 1 的一维数组。
在计算两行之间的列的和的时候,用动态规划算法提高速度。用一个数组 sumarray 记录某位置及该列以上所有元素的和。sumarray[i][j] = sum of matrix[0][j], matrix[1][j] … matrix[i][j]。然后求两行直接的列和的时候直接用 sumarray 做差即可。

class Solution:
    '''
    给一个包含0和1的列表,求最长连续子序列
    '''
    def findMaxSequence(self, l: 'List[int]') -> 'int':
        length= len(l)
        max_length = 0
        if length == 0:
            return 0
        
        dp = [0 for i in range(length)]
        
        if l[0] == 1:
            dp[0] = 1
        
        for i in range(1, length):
            if l[i] == 1:
                if l[i-1] == 0:
                    dp[i] = 1
                else:
                    dp[i] = dp[i-1] + 1
            else:
                dp[i] = 0
        
        for i in range(length):
            max_length = max(max_length, dp[i])
        
        return max_length
    
    def maximalRectangle(self, matrix: 'List[List[str]]') -> 'int':
        rows = len(matrix)
        
        if rows > 0:
            cols = len(matrix[0])
        max_area = 0
        
        if rows==0 or cols==0:
            return 0
        
        # transfer it to an 'int' array
        for i in range(rows):
            for j in range(cols):
                matrix[i][j] = int(matrix[i][j])
        
        # sumarray[i][j]: sum of matrix[0][j], matrix[1][j] ... matrix[i][j]
        sumarray = matrix.copy()
        for i in range(1, rows):
            for j in range(cols):
                sumarray[i][j] = sumarray[i-1][j] + sumarray[i][j]
        
        for i in range(rows):
            for j in range(i, rows):
                if (j-i+1)*cols < max_area:
                    continue
                tmparray = []
                for k in range(cols):
                    if i == 0:
                        delta = sumarray[j][k]
                    else:
                        delta = sumarray[j][k] - sumarray[i-1][k]
                    
                    if delta == (j-i+1):
                        tmparray.append(1)
                    else:
                        tmparray.append(0)
                
                # pruning
                if sum(tmparray)*(j-i+1) < max_area:
                    continue
                    
                max_sequence = self.findMaxSequence(tmparray)
                max_area = max(max_area, max_sequence * (j-i+1))
                
        return max_area
        
Solution 2

92 ms AC.
联系 LeetCode 84. Largest Rectangle in Histogram,将二维矩阵问题转化为直方图中最大矩阵面积的问题。逐行遍历,遍历到第 row 行时,只看第 row 行及其以上的部分。heights[j] 表示 matrix[i][j] 这个元素及其以上的连续的 ‘1’ 的个数。所以当前行计算出的 heights 数组其实可以代表一个直方图,然后用 84 题中的算法(这里提供一个笔者的解题博客)计算直方图中最大矩阵面积。遍历完所有行之后,得到整个矩阵的最大长方形面积。

matrix:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1 
1 0 0 1 0

heights:
1 0 1 0 0
2 0 2 1 1
3 1 3 2 2
4 0 0 3 0

然后在第三行 3 1 3 2 2 时,得到直方图中最大矩阵面积是6,也是全局最优解。

class Solution:
    '''
    calculate the max area in the histogram
    '''
    def largestRectangInHistogram(self, row):
        heights = [0] + row + [0]
        stack = []
        max_area = 0
        
        for i in range(len(heights)):
            if len(stack) == 0:
                stack.append(i)
            else:
                while len(stack)>0 and heights[stack[-1]] > heights[i]:
                    top = stack.pop()
                    max_area = max(max_area, heights[top] * (i-stack[-1]-1))
                stack.append(i)
        return max_area
    
    def maximalRectangle(self, matrix: 'List[List[str]]') -> 'int':
        rows = len(matrix)
        max_area = 0
        
        if rows > 0:
            cols = len(matrix[0])
        else:
            return 0
        
        # heights[i]: Number of consecutive '1' above matrix[i][j] (including matrix[i][j])
        heights = [0 for i in range(cols)]
        
        for i in range(rows):
            for j in range(cols):
                if matrix[i][j] == '1':
                    heights[j] = heights[j] + 1
                else:
                    heights[j] = 0
            max_rectangle_this_row = self.largestRectangInHistogram(heights)
            max_area = max(max_area, max_rectangle_this_row)    
                
        return max_area
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值