Maximal Square
Maximal Square is a medium dynamic programming problem solved with the squares pattern.
The best approach, optimal (dp on the bottom-right corner), runs in O(m · n) time and O(n) space.
Below are 2 approaches in Java, from brute force (grow squares) up.
Problem
In a binary matrix, find the largest square containing only 1s and return its area.
Examples
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
4- Why
- A 2 × 2 square of 1s.
Example 2
- Input
matrix = [[0]]- Output
0
Constraints
1 <= m, n <= 300; cells are '0' or '1'.- Return the area.
Animated walkthrough
A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.
Concepts first, then the problem and every approach, step by step.
Space to play or pause · ← → to jump a step · click or drag the bar to seek
Solutions
Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.
| Approach | Time | Space |
|---|---|---|
| Brute force (grow squares) | O((m · n)²) | O(1) |
| Optimal (DP on the bottom-right corner) | O(m · n) | O(n) |
1Brute force (grow squares)
O((m · n)²)O(1)From every 1, try to grow the square one layer at a time, checking the new row and column.
- For each cell, increase the size while the next ring is all 1s.
class Solution {
public int maximalSquare(char[][] matrix) {
int m = matrix.length, n = matrix[0].length, best = 0;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
int size = 0;
grow:
while (i + size < m && j + size < n) {
for (int k = 0; k <= size; k++)
if (matrix[i + size][j + k] != '1' || matrix[i + k][j + size] != '1') break grow;
size++;
}
best = Math.max(best, size);
}
return best * best;
}
}2Optimal (DP on the bottom-right corner)
O(m · n)O(n)A square ending at (i, j) can only be as big as the smallest of the three squares ending at its top, left and top-left neighbours, plus one. Keep one row of the table plus the diagonal value.
- If the cell is '1': dp[i][j] = 1 + min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]).
- Track the largest side; return side².
class Solution {
public int maximalSquare(char[][] matrix) {
int n = matrix[0].length, best = 0;
int[] dp = new int[n + 1];
for (char[] row : matrix) {
int diag = 0;
for (int j = 1; j <= n; j++) {
int up = dp[j];
dp[j] = row[j - 1] == '1' ? 1 + Math.min(Math.min(dp[j], dp[j - 1]), diag) : 0;
diag = up;
best = Math.max(best, dp[j]);
}
}
return best * best;
}
}Edge cases to test
- No 1s at all
- Single row or column
Hints
Hint 1
dp[i][j] = side of the largest square whose bottom-right corner is (i, j) = 1 + min(top, left, top-left).
FAQ
What is the best time complexity for Maximal Square?
Optimal (DP on the bottom-right corner) runs in O(m · n) time and O(n) extra space.
Which pattern does Maximal Square use?
It is a dynamic programming problem that uses the squares pattern. Other problems with the same pattern: Count Square Submatrices with All Ones, Largest 1-Bordered Square.
Is there a brute force solution for Maximal Square?
Yes. Brute force (grow squares) takes O((m · n)²) time and O(1) space. From every 1, try to grow the square one layer at a time, checking the new row and column.
Which edge cases should I test for Maximal Square?
No 1s at all; Single row or column.