You are 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.
Example 1:
Input: matrix = [
["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]
]
Output: 4Example 2:
Input: matrix = [
["0","1"],
["1","0"]
]
Output: 1Constraints:
1 <= matrix.length, matrix[i].length <= 300matrix[i][j] is '0' or '1'.Before attempting this problem, you should be comfortable with:
For each cell containing a '1', we can try to expand a square outward as far as possible. Starting with a 1x1 square, we incrementally check if we can form a 2x2, 3x3, and so on. For each size, we only need to verify the new rightmost column and bottommost row that would be added. If any cell in those edges is '0', we cannot expand further. This approach checks all potential squares explicitly.
(r, c) in the matrix.matrix[r][c] is '0', skip it.k starting at 1:r + k and c + k are within bounds.'1'.'0', stop expanding.k * k if the square is valid.class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
m, n = len(matrix), len(matrix[0])
res = 0
for r in range(m):
for c in range(n):
if matrix[r][c] == "0":
continue
k = 1
while True:
if r + k > m or c + k > n:
break
flag = True
for i in range(r, r + k):
if matrix[i][c + k - 1] == "0":
flag = False
break
for j in range(c, c + k):
if matrix[r + k - 1][j] == "0":
flag = False
break
if not flag:
break
res = max(res, k * k)
k += 1
return resWhere is the number of rows and is the number columns.
We can define a recursive function where dp(r, c) returns the side length of the largest square whose top-left corner is at (r, c). For a cell with '1', the answer depends on how far we can extend to the right, down, and diagonally. The limiting factor is the minimum of these three directions. We memoize results to avoid redundant computation, then scan all cells to find the maximum value.
-1 (unvisited).dfs(r, c):0.dfs(r+1, c), dfs(r, c+1), and dfs(r+1, c+1).matrix[r][c] is '1', set dp[r][c] = 1 + min(down, right, diag).dp[r][c] = 0.dfs(0, 0) to fill the table.class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
ROWS, COLS = len(matrix), len(matrix[0])
cache = {}
def dfs(r, c):
if r >= ROWS or c >= COLS:
return 0
if (r, c) not in cache:
down = dfs(r + 1, c)
right = dfs(r, c + 1)
diag = dfs(r + 1, c + 1)
cache[(r, c)] = 0
if matrix[r][c] == "1":
cache[(r, c)] = 1 + min(down, right, diag)
return cache[(r, c)]
dfs(0, 0)
return max(cache.values()) ** 2Where is the number of rows and is the number columns.
Instead of recursion, we can fill the DP table iteratively from bottom-right to top-left. For each '1' cell, the largest square ending there (as the bottom-right corner) is determined by the minimum of the squares ending at its right, bottom, and diagonal neighbors, plus one. This builds up from smaller subproblems to larger ones and avoids recursion overhead.
(m+1) x (n+1) initialized to 0.r = m-1 down to 0, and c = n-1 down to 0:matrix[r][c] is '1', set dp[r][c] = 1 + min(dp[r+1][c], dp[r][c+1], dp[r+1][c+1]).maxSquare with dp[r][c].maxSquare * maxSquare.class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
m, n = len(matrix), len(matrix[0])
dp = [[0] * (n + 1) for _ in range(m + 1)]
max_square = 0
for r in range(m - 1, -1, -1):
for c in range(n - 1, -1, -1):
if matrix[r][c] == "1":
dp[r][c] = 1 + min(dp[r + 1][c], dp[r][c + 1], dp[r + 1][c + 1])
max_square = max(max_square, dp[r][c])
return max_square * max_squareWhere is the number of rows and is the number columns.
The bottom-up DP only needs the current row and the next row to compute values. We can reduce space by using a single 1D array. As we process each row from right to left, we keep track of the previous diagonal value in a variable prev. This allows us to update the array in place while still having access to all three neighbors needed for the recurrence.
n+1 initialized to 0.r = m-1 down to 0:prev = 0 (represents the diagonal value from the previous iteration).c from n-1 down to 0:dp[c] in temp (this will be the next diagonal).matrix[r][c] is '1', set dp[c] = 1 + min(dp[c], dp[c+1], prev) and update maxSquare.dp[c] = 0.prev = temp.maxSquare * maxSquare.class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
m, n = len(matrix), len(matrix[0])
dp = [0] * (n + 1)
max_square = 0
for r in range(m - 1, -1, -1):
prev = 0
for c in range(n - 1, -1, -1):
temp = dp[c]
if matrix[r][c] == "1":
dp[c] = 1 + min(dp[c], dp[c + 1], prev)
max_square = max(max_square, dp[c])
else:
dp[c] = 0
prev = temp
return max_square * max_squareWhere is the number of rows and is the number columns.
The DP table stores the side length of the largest square, but the problem asks for the area. Forgetting to square the maximum side length before returning gives an incorrect answer.
Matrix elements are characters ('0' and '1'), not integers. Comparing against integer 0 or 1 instead of character '0' or '1' causes the condition to always evaluate incorrectly, resulting in wrong DP values.
The recurrence dp[r][c] = 1 + min(dp[r+1][c], dp[r][c+1], dp[r+1][c+1]) assumes processing from bottom-right to top-left. Processing in the wrong direction (top-left to bottom-right without adjusting the formula) references uncomputed values and produces incorrect results.