Given a m * n
matrix of ones and zeros, return how many square submatrices have all ones.
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
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine you have a grid of squares, some filled with 1s and some with 0s. We want to find all the square shapes inside the grid that are completely filled with 1s. The brute force method is like checking every possible square, one by one, to see if it works.
Here's how the algorithm would work step-by-step:
def count_square_submatrices_brute_force(matrix):
rows = len(matrix)
cols = len(matrix[0]) if rows > 0 else 0
total_square_count = 0
# Iterate through all possible square sizes
for square_side in range(1, min(rows, cols) + 1):
# Iterate through the matrix to check each possible top-left corner.
for row_start in range(rows - square_side + 1):
for col_start in range(cols - square_side + 1):
is_all_ones = True
# Check if the current square has all ones
for row_index in range(row_start, row_start + square_side):
for col_index in range(col_start, col_start + square_side):
if matrix[row_index][col_index] == 0:
is_all_ones = False
break
if not is_all_ones:
break
# Increment the count if the square contains all ones
if is_all_ones:
total_square_count += 1
return total_square_count
The core idea is to avoid redundant calculations by building up square sizes from smaller ones. We use the input grid to store the size of the largest square ending at each cell. This way, we only need to check a few neighbors to decide the size of a larger square.
Here's how the algorithm would work step-by-step:
def count_squares(matrix):
total_square_count = 0
rows = len(matrix)
columns = len(matrix[0])
for row_index in range(rows):
for column_index in range(columns):
if matrix[row_index][column_index] == 1:
# Find min of neighbors to determine square size.
if row_index > 0 and column_index > 0:
matrix[row_index][column_index] = min(
matrix[row_index - 1][column_index],
matrix[row_index][column_index - 1],
matrix[row_index - 1][column_index - 1]
) + 1
# Add current square size to overall count.
total_square_count += matrix[row_index][column_index]
return total_square_count
Case | How to Handle |
---|---|
Null or empty matrix input | Return 0 immediately since no submatrices can exist. |
Matrix with 0 rows or 0 columns | Return 0 immediately as a matrix is effectively empty. |
Matrix with 1 row and 1 column (single element) | Return 1 if the single element is 1, otherwise return 0. |
Matrix with all 0s | Return 0 as there are no square submatrices with all 1s. |
Matrix with all 1s | Calculate the number of square submatrices by iterating through possible sizes and counts them. |
Large matrix dimensions potentially causing integer overflow when counting | Use a larger integer data type (e.g., long) for the count to prevent overflow. |
Rectangular matrix (number of rows != number of columns) | The algorithm should correctly handle rectangular matrices by considering the minimum dimension when determining the maximum possible square size. |
Matrix with alternating 0s and 1s (checkerboard pattern) | The algorithm should correctly identify and count any valid square submatrices of 1s. |