This is a dynamic programming problem. We start at the top left and work our way down to the bottom right. For each cell we calculate the largest possible rectangle at that position. If the cell is 0 then the rectangle is 0 and we move on.
If the cell is 1 then we have more work to do. There will be a rectangle of minimum size 1 at this cell, but there could be bigger rectangles. We check then neighbors to see if we can then
The solution makes two passes. The first checks to see how many long a row of 1's goes for each cell, and the second checks for the longest column of 1's. After checking the current row/column, the algorithm then tries to see if there is a neighboring rectangle that this cell could be part of.
O(n^2) time
O(n^2) space
class Solution:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
area = 0
if not matrix:
return area
dp = [[(0,0)] * len(matrix[0]) for _ in range(len(matrix))]
def calcArea(tpl):
return tpl[0] * tpl[1]
for i in range(len(matrix)):
prevHort = 0
for j in range(len(matrix[i])):
if matrix[i][j] == "1":
prevHort += 1
dp[i][j] = (prevHort, 1)
if i > 0:
prevWidth, prevHeight = dp[i - 1][j]
extendUp = (min(prevHort, prevWidth), prevHeight + 1)
if calcArea(extendUp) > calcArea(dp[i][j]):
dp[i][j] = extendUp
area = max(area, calcArea(dp[i][j]))
else:
prevHort = 0
for j in range(len(matrix[0])):
prevVert = 0
for i in range(len(matrix)):
if matrix[i][j] == "1":
prevVert += 1
dp[i][j] = (1, prevVert)
if j > 0:
prevWidth, prevHeight = dp[i][j - 1]
extendLeft = (prevWidth + 1, min(prevVert, prevHeight))
if calcArea(extendLeft) > calcArea(dp[i][j]):
dp[i][j] = extendLeft
area = max(area, calcArea(dp[i][j]))
else:
prevVert = 0
dp[i][j] = (0,0)
return area