Count Square Submatrices with All Ones

Medium2D Grid DP · Square Ending Here🧩 Grid DPLeetCode #1277 ↗Updated

Problem

You get an m × n grid made only of 0s and 1s. Count how many square sub-grids (of any size, at any position) contain nothing but 1s. Squares of different sizes or positions are counted separately.
Input[[0,1,1,1],[1,1,1,1],[0,1,1,1]]Output15
Input[[1,0,1],[1,1,0],[1,1,0]]Output7

1 ≤ m, n ≤ 300  ·  matrix[i][j] ∈ {0, 1}

Try it yourself

Java
class Solution {
    public int countSquares(int[][] matrix) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Let dp[i][j] = side of the largest all-ones square whose bottom-right corner is (i,j). It is also the number of squares ending there (sides 1..dp), so the answer is simply the sum of all dp values.
PatternGrid DP

Instinct Grid moves that never loop back (right/down, row to row) plus "count or optimise the paths" - build dp[r][c] from the cells that can step in.

Memory hack Every cell asks its parents - a cell's answer comes only from the neighbours that can move into it, so fill cells in the order they arrive.

Open the Grid DP guide →

Approaches

Brute ForceGrow Every Square & Re-check

Time O(m·n·k3)Space O(1)

For every top-left cell, try sides 1, 2, … up to k = min(m, n) and scan the whole square for a 0. Once a side fails, every larger square from that corner contains it too, so stop early. Re-scanning size2 cells per side gives the cubic factor.

Java
public int countSquares(int[][] matrix) {
    int m = matrix.length, n = matrix[0].length, count = 0;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            for (int size = 1; size <= Math.min(m - i, n - j); size++) {
                if (!allOnes(matrix, i, j, size)) break; // bigger ones fail too
                count++;
            }
    return count;
}
private boolean allOnes(int[][] a, int r, int c, int size) {
    for (int i = r; i < r + size; i++)
        for (int j = c; j < c + size; j++)
            if (a[i][j] != 1) return false;
    return true;
}

Simple and obviously correct, but repeats almost all of its work.

At a glance

LevelApproachTimeSpace
Brute ForceGrow Every Square & Re-checkO(m·n·k3)O(1)
Better2-D DP (Bottom-Right Corner)O(m·n)O(m·n)
Optimal1-D Rolling RowO(m·n)O(n)
Common pitfalls
  • Counting only the largest square per cell — a side-3 square also contains sides 1 and 2.
  • Taking min of only top and left — the diagonal neighbour matters too.
  • Rolling row: reading the updated dp[j] as “above” — save it first.
Interview tips
  • Name the state precisely: largest square ending at (i,j) as bottom-right.
  • Explain why dp[i][j] doubles as a count of squares ending there.
  • Link it to Maximal Square (221): same table, take max instead of sum.
Pattern
2-D grid DP over corners → count or size squares/rectangles built from neighbouring sub-answers.
My notes saved in this browser