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: 4
Example 2:
Input: matrix = [["0","1"],["1","0"]] Output: 1
Example 3:
Input: matrix = [["0"]] Output: 0
Constraints:
m == matrix.lengthn == matrix[i].length1 <= m, n <= 300matrix[i][j] is '0' or '1'.Problem Overview: Given a binary matrix filled with '0's and '1's, find the area of the largest square containing only '1's. You must determine the side length of the biggest valid square and return its area.
Approach 1: Brute Force Expansion (O((m*n)*min(m,n)^2) time, O(1) space)
Check every cell as a potential top-left corner of a square. When a cell contains '1', expand the square diagonally while verifying that the newly added row and column still contain only '1'. This requires repeatedly scanning matrix regions, which becomes expensive for large inputs. The approach is useful for understanding the structure of the problem but performs poorly because each expansion re-validates previously checked cells.
Approach 2: Dynamic Programming (O(m*n) time, O(m*n) space)
The key insight: a square ending at position (i, j) depends on its neighbors. If the current cell contains '1', the largest square ending here equals 1 + min(top, left, top-left). These three cells represent the largest squares that could extend into the current cell. Build a DP table where dp[i][j] stores the side length of the largest square ending at that position. Iterate through the grid once, update values using the recurrence relation, and track the maximum side length seen. This classic dynamic programming pattern avoids rechecking regions and converts the problem into local state transitions.
Approach 3: Space Optimized Dynamic Programming (O(m*n) time, O(n) space)
The DP transition only depends on the current row and the previous row. Instead of storing a full m x n table, maintain a 1D array representing the previous row while iterating across columns. A temporary variable tracks the previous diagonal value (top-left) during updates. Each step performs the same min() transition but reuses memory, reducing space complexity to O(n). This version is preferred when matrix dimensions are large or memory constraints matter. The algorithm still scans the grid once and applies constant-time transitions for each cell.
Recommended for interviews: The Dynamic Programming approach with the min(top, left, diagonal) recurrence is the expected solution. Interviewers want to see that you recognize the overlapping substructure and convert it into a DP state transition. Mentioning the brute force expansion shows problem exploration, while implementing the optimized DP demonstrates strong understanding of array and matrix-based DP patterns.
In this approach, a dynamic programming (DP) table is used to store the size of the largest square whose bottom-right corner is at each cell. For each cell (i, j) with a value of '1', we check its top (i-1, j), left (i, j-1), and top-left (i-1, j-1) neighbors to determine the size of the largest square ending at (i, j). If any of these neighbors are '0', the square cannot extend to include (i, j). The formula is: dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1. The maximum value in the DP table will be the side length of the largest square, and the area is its square.
The Python solution initializes a DP table with one extra row and column filled with zeros, to handle boundary conditions without additional checks. It iterates through the matrix, updating the DP table using the given formula and tracking the maximum square side found.
C
C++
Java
C#
JavaScript
Time Complexity: O(m * n), where m is the number of rows and n is the number of columns.
Space Complexity: O(m * n), due to the DP table.
This approach uses a similar DP strategy but optimizes space by utilizing a one-dimensional array instead of a full 2D DP table. The key idea is that while processing the matrix row by row, previous rows' information will be partially redundant. Hence, we can maintain only the current and previous row data in separate arrays or even use a single array with swap states.
The space-optimized Python solution uses two arrays; one for the current row calculations and one for the previous row's data. After finishing each row, it swaps the references, reassigning the current as 'previous'. This approach reduces space use to O(n).
C
C++
Java
C#
JavaScript
Time Complexity: O(m * n)
Space Complexity: O(n)
| Approach | Complexity |
|---|---|
| Dynamic Programming Approach | Time Complexity: O(m * n), where m is the number of rows and n is the number of columns. |
| Space Optimized DP Approach | Time Complexity: O(m * n) |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force Expansion | O((m*n)*min(m,n)^2) | O(1) | Conceptual understanding or very small matrices |
| Dynamic Programming | O(m*n) | O(m*n) | General case and standard interview solution |
| Space Optimized DP | O(m*n) | O(n) | Large matrices or memory constrained environments |
DP 55. Maximum Rectangle Area with all 1's | DP on Rectangles • take U forward • 161,020 views views
Watch 9 more video solutions →Practice Maximal Square with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor