2Brute2Best
🔥0

Maximal Square

Medium·LeetCode #221Basic Anchor
LeetCode
30-Second Mental ModelDP — Grid, Squares and shapes (dp[r][c] = 1 + min(top, left, top-left))
Complexity:O(M · N · min(M, N)³)→O(M · N)
Key Insight

Let dp[r][c] be the side of the biggest all-ones square whose bottom-right corner is (r, c). If the cell is '1', the square can only be as big as its weakest neighbour allows: dp[r][c] = 1 + min(top, left, top-left). Each cell only reads three neighbours, so we only need the previous row.

Core Validity Invariant

A square of side s can end at (r, c) only if the top, left and top-left cells each end a square of side s − 1. So dp[r][c] is 1 plus the smallest of those three values.

01

Problem

You get a grid made of '0' and '1' characters. Find the biggest square that is filled only with '1' cells.

Return the area of that square, not its side length. For example, a 2 × 2 square of ones has area 4.

Input

A grid matrix with m rows and n columns. Each cell is the character '0' or '1'.

Output

The area of the largest all-'1' square. If there is no '1' at all, the answer is 0.

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

The biggest square of ones is 2 × 2, so its area is 4. The block at rows 1–2 and columns 3–4 is all ones.

Example 2
Input: matrix = [["0","1"], ["1","0"]]
Output: 1

No 2 × 2 block is all ones. A single '1' is a square of side 1, so the area is 1.

Example 3
Input: matrix = [["0"]]
Output: 0

There is no '1' at all, so no square counts.

Constraints
  • • 1 ≤ m, n ≤ 300
  • • Each cell is `'0'` or `'1'`.
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    A square with side k and bottom-right corner (r, c) needs which cells to be all ones?

  2. 2.

    If I know the biggest square that ends at the cell above, and the one that ends at the cell to the left, what limits the square that ends here?

  3. 3.

    Can a square end at (r, c) if the cell at (r − 1, c − 1) is 0? What does that tell me?

  4. 4.

    Is the output a side length or an area? Read the output line again.

  5. 5.

    Can I check a square without reading all of its cells, if I already know the squares around it?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceTry every top-left corner and every side, and check every cell of each squareO(M · N · min(M, N)³)O(1)
BetterCount the ones in any square with a prefix-sum table; the square is all ones when the count is k × kO(M · N · min(M, N))O(M · N)
Optimaldp[r][c] = 1 + min(top, left, top-left) on a 1; keep one row and the diagonalO(M · N)O(N)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “largest square”The answer is a square, not any rectangle. A square grows one ring at a time, so its side can be tracked in a table.
  • “filled only with 1s”A `'0'` cell stops every square that would cover it, so a 0 resets its dp value.
  • “return its area”The table tracks the side. The answer is side × side.
2-D grid+square that ends at each corner+min of three neighbours plus 1→DP — Grid, Squares and shapes (dp[r][c] = 1 + min(top, left, top-left))

This is the anchor of Squares and shapes. At each cell the only question is how far a square can reach up and to the left, and the answer is the minimum of the three neighbours. Count Square Submatrices with All Ones uses the same table, but it adds up every cell instead of taking the maximum.

10

Don't make this mistake

Pattern confusion: using only the top and left neighbours
✗ dp[r][c] = 1 + min(dp[r-1][c], dp[r][c-1]);
✓ dp[r][c] = 1 + min(dp[r-1][c], dp[r][c-1], dp[r-1][c-1]);

The top-left cell can be '0' even when the top and left are both '1'. On the grid [["0","1"], ["1","1"]] the bottom-right cell has top 1 and left 1, so the wrong rule gives side 2 (area 4). But the 2 × 2 square would need the top-left cell, which is 0. The true answer is area 1.

Returning the side instead of the area
✗ return best;
✓ return best * best;

The question asks for the area. On example 1 the biggest side is 2, so the wrong code returns 2 instead of 4.

One-row version forgets to reset a 0 cell
✗ if (matrix[r][c-1] == '1') dp[c] = 1 + min({above, dp[c-1], diag});
✓ dp[c] = matrix[r][c-1] == '1' ? 1 + min({above, dp[c-1], diag}) : 0;

A '0' cell must set dp to 0. Without that, the cell keeps the value from the row above. On the grid [["1","1"], ["0","1"]] the cell below the first '1' keeps a stale 1, so the bottom-right cell wrongly gets side 2 (area 4). The answer is 1, because the 2 × 2 square has a '0' in it.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like DP — Grid translate into production architectures and low-level memory mechanics.