221. lc0221 maximal square¶
Problem Description¶
LeetCode Problem 221:
Given an m x n
binary matrix
filled with 0
's and 1
's, find the largest square
containing only 1
's and return its area.
Clarification¶
-
Assumption¶
- The matrix is not square
- Need to find the largest square
- Area (width x height)
- The matrix could be empty
Solution¶
Approach 1: Dynamic Programming¶
To form a square k + 1
at (i, j)
, we need to ensure that:
- A square of size
k
exists above,(i - 1, j)
- A square of size
k
exists to the left,(i, j - 1)
- A square of size
k
exists diagonally top-left,(i - 1, j - 1)
This problem can be solved using dynamic programming:
- State:
dp(i, j)
represents the side length of the largest square whose bottom-right corner is at(i, j)
in the input matrix. - State Transition:
- If
matrix[i][j] == "1"
, thendp(i, j)
is the minimum of the top, left, and top-left neighbors plus one:dp(i, j) = min(dp(i-1, j), dp(i, j-1), dp(i-1, j-1)) + 1
- If
matrix[i][j] == "0"
, then:dp(i, j) = 0
- If
- Base Case: If
i == 0
orj == 0
, thendp(i, j) = matrix[i][j]
(if it's "1") or0
(if it's "0").
For the space complexity optimization, we can
- Start from a 2D array of size
(m + 1) x (n + 1)
for better understanding - Reduce it to two 1D arrays of size
n + 1
, one for the current row and one for the previous row - Further reduce it to a single 1D array of size
n + 1
. It is tricky to understand and implement it correctly.
graph LR
2d["2D Array"] --> two1d["Two 1D Arrays"] --> 1d["1D Array"]
block-beta
columns 14
block:2dArray:4
columns 2
topLeft2d["dp(i-1, j-1)"] top2d["dp(i-1, j)"]
left2d["dp(i, j-1)"] bottomRight2d["dp(i, j)"]
end
space
block:two1dArrays:4
columns 2
topLeft21d["prev[j-1]"] top21d["prev[j]"]
left21d["curr[j-1]"] bottomRight21d["curr[j]"]
end
space
block:1dArray:4
columns 2
topLeft1d["prev, old dp[i-1]"] top1d["dp[i]"]
left1d["dp[i-1]"] bottomRight1d["new dp[i]"]
end
2dArray --> two1dArrays
two1dArrays --> 1dArray
style bottomRight2d fill:orange,stroke:#333,stroke-width:2px
style bottomRight21d fill:orange,stroke:#333,stroke-width:2px
style bottomRight1d fill:orange,stroke:#333,stroke-width:2px
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
n_rows = len(matrix)
n_cols = len(matrix[0]) if n_rows else 0
dp = [
[0] * (n_cols + 1) for _ in range(n_rows + 1)
] # Add extra rows and columns to facility dp computations for the first row and the first column in matrix
max_sq_len = 0
for i in range(n_rows):
for j in range(n_cols):
if matrix[i][j] == "1":
dp[i + 1][j + 1] = (
min([dp[i][j + 1], dp[i + 1][j], dp[i][j]]) + 1
) # Be careful of the indexing, (i, j) in matrix correspond to (i + 1, j + 1) in dp
max_sq_len = max(max_sq_len, dp[i + 1][j + 1])
return max_sq_len * max_sq_len
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
if not matrix or not matrix[0]:
return 0
n_rows, n_cols = len(matrix), len(matrix[0])
prev = [0] * (n_cols + 1)
max_side = 0
for i in range(1, n_rows + 1):
curr = [0] * (n_cols + 1)
for j in range(1, n_cols + 1):
if matrix[i - 1][j - 1] == "1":
curr[j] = min(prev[j - 1], prev[j], curr[j - 1]) + 1
max_side = max(max_side, curr[j])
prev = curr
return max_side * max_side
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
if not matrix:
return 0
n_rows, n_cols = len(matrix), len(matrix[0])
dp = [0] * (n_cols + 1)
max_sq_len = 0
prev = 0
for i in range(n_rows):
for j in range(n_cols):
temp = dp[j + 1]
if matrix[i][j] == "1":
dp[j + 1] = min([dp[j + 1], dp[j], prev]) + 1
max_sq_len = max(max_sq_len, dp[j + 1])
else:
dp[j + 1] = 0
prev = temp
return max_sq_len * max_sq_len
Complexity Analysis of Approach 1¶
- Time complexity: \(O(m \times n)\)
We need to iterate through each cell in the matrix once. - Space complexity: \(O(n)\) for 1D array implementation, \(O(m \times n)\) for 2D array
implementation
- For 2D array implementation, we use a 2D array of size \((m + 1) \times (n + 1)\).
- For two 1D arrays implementation, we use two 1D arrays of size \(n + 1\).
- For 1D array implementation, we use a 1D array of size \(n + 1\).
Test¶
- Test empty matrix
- Test matrix with single row or single column
- Test matrix with all "0"s
- Test matrix with all "1"s
- Test matrix with mixed "0"s and "1"s