Count Square Submatrices with All Ones
Solve this Problemmatrix, count how many square submatrices — of any size, 1×1 and up — are made entirely of 1s.
Trying every square directly, with a prefix-sum table to check each one in O(1), already works. The faster way notices something sharper: define dp[r][c] as the side length of the biggest all-1s square that has its bottom-right corner exactly at (r, c). That value can only grow past 1 if a square one size smaller already ends at the cell above, the cell to the left, *and* the cell diagonally above-left — so dp[r][c] is the smallest of those three neighbors, plus one. The neat payoff: dp[r][c] doesn't just say how big the largest square there is, it also equals how many squares of every size up to that end there — a size-3 square ending somewhere means a size-2 and a size-1 do too, at the very same corner. Summing dp[r][c] across the whole grid is the answer.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ rows, cols ≤ 200 - ◆
every entry of matrix is either 0 or 1
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Prefix Sums Over Every Candidate Square
BruteFor every possible top-left corner, try every possible square size that still fits within the grid from there, and use a 2D prefix-sum table to check in O(1) whether that size×size region is entirely 1s. There are O(R·C) starting corners and up to O(min(R,C)) sizes to try from each one.
O(R · C · min(R, C))O(R · C)1class Solution {
2 public int countSquares(int[][] matrix) {
3 int rows = matrix.length;
4 if (rows == 0) return 0;
5 int cols = matrix[0].length;
6 int[][] prefix = new int[rows + 1][cols + 1];
7 for (int r = 0; r < rows; r++) {
8 for (int c = 0; c < cols; c++) {
9 prefix[r + 1][c + 1] = matrix[r][c] + prefix[r][c + 1] + prefix[r + 1][c] - prefix[r][c];
10 }
11 }
12 int count = 0;
13 for (int top = 0; top < rows; top++) {
14 for (int left = 0; left < cols; left++) {
15 int maxSize = Math.min(rows - top, cols - left);
16 for (int size = 1; size <= maxSize; size++) {
17 int bottom = top + size - 1;
18 int right = left + size - 1;
19 int sum = prefix[bottom + 1][right + 1] - prefix[top][right + 1] - prefix[bottom + 1][left] + prefix[top][left];
20 if (sum == size * size) {
21 count++;
22 }
23 }
24 }
25 }
26 return count;
27 }
28}Optimal — DP: Largest Square Ending at Each Cell
OptimalLet dp[r][c] be the side length of the largest all-1s square whose bottom-right corner is exactly cell (r, c). If matrix[r][c] is 0, no square can end there — dp[r][c] = 0. Otherwise a square of side k can only end here if squares of side k-1 already end at the cell above, the cell to the left, and the cell diagonally above-left — so dp[r][c] is one more than the smallest of those three neighbors. The key trick: dp[r][c] doesn't just tell you the biggest square ending there — it tells you exactly how many squares (of every size from 1 up to dp[r][c]) end there, since every smaller size is automatically achievable too. Summing dp[r][c] over the whole grid is the total count.
O(R · C)O(R · C)1class Solution {
2 public int countSquares(int[][] matrix) {
3 int rows = matrix.length;
4 if (rows == 0) return 0;
5 int cols = matrix[0].length;
6 int[][] dp = new int[rows][cols];
7 int count = 0;
8 for (int r = 0; r < rows; r++) {
9 for (int c = 0; c < cols; c++) {
10 if (matrix[r][c] == 0) {
11 dp[r][c] = 0;
12 } else if (r == 0 || c == 0) {
13 dp[r][c] = 1;
14 } else {
15 dp[r][c] = Math.min(dp[r - 1][c], Math.min(dp[r][c - 1], dp[r - 1][c - 1])) + 1;
16 }
17 count += dp[r][c];
18 }
19 }
20 return count;
21 }
22}