Count Square Submatrices with All Ones

Updated on 09 May, 2025
Count Square Submatrices with All Ones header image

Problem Statement

The task is to determine the number of square submatrices within a given m x n matrix where all elements are either 1 or 0. Specifically, you need to count all possible submatrices where every element is 1. These submatrices can vary in size from a single cell (1x1) to larger squares potentially the size of the entire matrix (if the conditions fit). The challenge involves both identifying these submatrices and ensuring they are square in shape—meaning the height and width are equal.

Examples

Example 1

Input:

matrix =
[
  [0,1,1,1],
  [1,1,1,1],
  [0,1,1,1]
]

Output:

15

Explanation:

There are 10 squares of side 1.
There are 4 squares of side 2.
There is 1 square of side 3.
Total number of squares = 10 + 4 + 1 = 15.

Example 2

Input:

matrix =
[
[1,0,1],
[1,1,0],
[1,1,0]
]

Output:

7

Explanation:

There are **6** squares of side 1.  
There is 1 square of side 2.
Total number of squares = 6 + 1 = **7**.

Constraints

  • 1 <= arr.length <= 300
  • 1 <= arr[0].length <= 300
  • 0 <= arr[i][j] <= 1

Approach and Intuition

To solve this problem, let's break down the concept using the provided examples and the constraints that govern the valid solutions:

  1. Understanding the Structure of Submatrices:

    • A square submatrix is determined by its smallest dimension since both dimensions must be equal for it to be considered a square. For instance, a 2x2 area within the larger matrix can be a square submatrix if all its entries are 1.
  2. Incremental Submatrix Expansion:

    • Starting from each cell that contains a 1, consider it as a potential top-left corner of a square submatrix. Expand this potential square by checking if a larger square that includes this cell as the top-left corner can be formed by verifying if all cells in the intended area are 1.
    • This expansion can continue until you either run out of matrix space or encounter a zero, which disqualifies the current expansion from forming a larger square.
  3. Dynamic Programming Approach:

    • Utilize a dynamic programming table where each entry at (i, j) represents the size of the largest square submatrix for which (i, j) is the bottom-right corner.
    • Populate this table by checking the smallest value among the immediate top, left, and top-left neighbors of the cell, which ensures forming a square. This minimizes repeated calculations and inefficiencies found in a naive approach.
  4. Summing Up Valid Squares:

    • The sum of all values in the dynamic programming table will give the total number of square submatrices. Each value directly contributes to count different size squares it possibly can be a part of.

By following the above steps, the problem transforms from a mere combinatorial challenge into a structured, step-wise calculation that leverages previous computations for efficient solution finding. The constraints ensure that while the input size may be large, it's manageable within the bounds to apply such an approach effectively.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int totalSquares(vector<vector<int>>& grid) {
        int rows = grid.size(), cols = grid[0].size(), total = 0, last = 0;
        vector<int> dynamicP(cols + 1, 0);

        for (int r = 1; r <= rows; r++) {
            for (int c = 1; c <= cols; c++) {
                if (grid[r - 1][c - 1] == 1) {
                    int tempVar = dynamicP[c];
                    dynamicP[c] = 1 + min(last, min(dynamicP[c - 1], dynamicP[c]));
                    last = tempVar;
                    total += dynamicP[c];
                } else {
                    dynamicP[c] = 0;
                }
            }
        }
        return total;
    }
};

This solution examines the problem of counting the number of square submatrices within a matrix with all elements equal to one. The provided code is implemented in C++ and utilizes dynamic programming to efficiently solve the problem.

The function totalSquares accepts a 2D vector<vector<int>> representing the grid and returns the total count of square submatrices where all elements are ones:

  • Start by determining the number of rows and columns in the grid.
  • Initialize a variable total to keep track of the total number of submatrices and a temporary variable last for dynamic programming computation.
  • A 1D vector<int>, dynamicP, holds the counts of squares terminating at certain positions and is initialized to have elements all set to zero.
  • Iterate over each element of the grid starting from the first row and column.
  • For every 1 in the grid, update dynamicP[c] to represent the size of the largest square submatrix terminating at that cell:
    • This involves taking the minimum of three values: last, dynamicP[c - 1], and dynamicP[c], and adding one.
    • The value of dynamicP[c] before updating is stored in tempVar.
    • Increment total by the value of dynamicP[c].
  • If a zero is found in the grid, set dynamicP[c] to zero since no square submatrix can end at a cell containing zero.
  • Return the accumulated total at the end of the function.

This approach ensures efficient computation by leveraging the previously calculated values to determine the largest possible square submatrix at each step, thereby optimizing the solution to a potential computationally expensive problem.

java
class Solution {

    public int countSubmatrices(int[][] grid) {
        int totalRows = grid.length, totalCols = grid[0].length, total = 0, last = 0;
        int[] memo = new int[totalCols + 1];

        for (int r = 1; r <= totalRows; r++) {
            for (int c = 1; c <= totalCols; c++) {
                if (grid[r - 1][c - 1] == 1) {
                    int save = memo[c];
                    memo[c] = 1 + Math.min(last, Math.min(memo[c - 1], memo[c]));
                    last = save;
                    total += memo[c];
                } else {
                    memo[c] = 0;
                }
            }
        }
        return total;
    }
}

This solution is for a problem where the objective is to count the number of submatrices that consist entirely of 1s within a given binary matrix. The provided code is in Java and implements a dynamic programming approach to solve this problem effectively.

Here is a simplified breakdown of how the code works:

  1. Initialize totalRows and totalCols, which represent the dimensions of the grid.
  2. Declare total to keep track of the total count of square submatrices.
  3. Use an array memo of size totalCols + 1 to store temporary results for dynamic programming.
  4. Iterate over each element of the grid starting from the first row and the first column using two nested loops.
  5. For each cell that contains a 1, calculate the size of the largest square submatrix ending at that cell using the values stored in memo.
  6. Update memo[c] with the size of the largest square plus one, which is dependent on the minimum sizes of submatrices ending at the top, left, and top-left diagonal of the current cell.
  7. Add the size of the current largest square submatrix to total.
  8. If the cell contains a 0, set memo[c] to 0 as no square submatrix can end at this cell.
  9. Finally, return the total which represents the count of all square submatrices filled with 1s.

The code leverages dynamic programming, which ensures optimal performance by storing intermediate results and using them in further calculations to build the final solution. This approach reduces the computational complexity compared to a naive method. The solution updates the memo array iteratively based on the values of previously computed cells in the same row and the cells from the previous row, making the process more memory-efficient.

python
class Solution:
    def totalSquares(self, grid: List[List[int]]) -> int:
        rows, cols, total, previous = len(grid), len(grid[0]), 0, 0
        dp_row = [0] * (cols + 1)

        for r in range(1, rows + 1):
            for c in range(1, cols + 1):
                if grid[r - 1][c - 1] == 1:
                    buffer = dp_row[c]
                    dp_row[c] = 1 + min(previous, min(dp_row[c - 1], dp_row[c]))
                    previous = buffer
                    total += dp_row[c]
                else:
                    dp_row[c] = 0

        return total

This Python code provides a solution for counting the number of square submatrices where all elements are ones, within a given 2D binary matrix. It uses dynamic programming for an efficient computation. Here's how the algorithm works:

  • Initialize some helper variables for handling dimensions of the input matrix (rows, cols) and for storing interim results (dp_row). total is used to accumulate the count of valid square submatrices.
  • Traverse through each cell in the matrix using a nested loop structure. For each element in the original matrix that is a one ('1'), update the current state in the dp_row which temporarily holds counts of square submatrices ending at the current cell.
  • The size of the largest square ending at a particular cell (r, c) is determined based on the smallest square that can be formed by also including the value of the cell above (r-1, c), the cell to the left (r, c-1), and the diagonal top-left cell (r-1, c-1). This is computed using the min function with an offset in the index that accommodates the transition between zero and one-based indexing.
  • If the current cell contains a zero ('0'), reset the count of possible square matrices for this position to zero.
  • Sum up all the calculated counts for each cell and return the accumulated value total, which represents the number of all possible square submatrices consisting entirely of ones.

This approach significantly reduces the computational complexity and provides a faster way to count such square submatrices compared to a brute-force method. It effectively leverages memory by only requiring a single row (dp_row) to store interim results, plus a few scalars.

Comments

No comments yet.