
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:
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.
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.
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.
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
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 variablelast
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]
, anddynamicP[c]
, and adding one. - The value of
dynamicP[c]
before updating is stored intempVar
. - Increment
total
by the value ofdynamicP[c]
.
- This involves taking the minimum of three values:
- 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.
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:
- Initialize
totalRows
andtotalCols
, which represent the dimensions of the grid. - Declare
total
to keep track of the total count of square submatrices. - Use an array
memo
of sizetotalCols + 1
to store temporary results for dynamic programming. - Iterate over each element of the grid starting from the first row and the first column using two nested loops.
- 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
. - 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. - Add the size of the current largest square submatrix to
total
. - If the cell contains a 0, set
memo[c]
to 0 as no square submatrix can end at this cell. - 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.
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 themin
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.
No comments yet.