Given an N*M matrix containing only 0s and 1s, the task is to count the number of square submatrices containing all 1s.
Examples:
Input: arr[][] = {{0, 1, 1, 1},
{1, 1, 1, 1},
{0, 1, 1, 1}}
Output: 15
Explanation:
There are 10 squares of side length 1.
There are 4 squares of side length 2.
There is 1 square of side length 3.
Total number of squares = 10 + 4 + 1 = 15.
Input: arr[][] = {{1, 0, 1},
{1, 1, 0},
{1, 1, 0}}
Output: 7
Naive Recursion Approach:
- At every position, we determine the maximum possible side length for a square if we consider that position as the top left corner. This maximum length can also contain smaller squares with lengths 2 and 1.
- Therefore, we can calculate the total number of squares by adding these lengths to our final answer.
- In summary, we can state that the largest square with coordinates (i,j) as the top left corner is equal to the total count of squares with (i,j) as the top left corner.
// C++ program to return the number of // square submatrices with all 1s #include <bits/stdc++.h> using namespace std;
// Function to solve the problem recursively int solve(vector<vector< int > >& matrix, int m, int n, int i,
int j)
{ // Base case: if out of bounds or current element is 0
if (i < 0 or i >= m or j < 0 or j >= n
or matrix[i][j] == 0) {
return 0;
}
// Recursive calls to calculate the number of squares in
// right, bottom, and bottom-right directions
int right = solve(matrix, m, n, i, j + 1);
int bottom = solve(matrix, m, n, i + 1, j);
int bottom_right = solve(matrix, m, n, i + 1, j + 1);
// Return the count of squares for the current position
return 1 + min({ right, bottom, bottom_right });
} // Function to return the number of square submatrices with // all 1s int countSquareMatrices(vector<vector< int > >& matrix)
{ int m = matrix.size();
int n = matrix[0].size();
int ans = 0;
// Iterate over each element of the matrix
for ( int i = 0; i < m; i++) {
for ( int j = 0; j < n; j++) {
if (matrix[i][j] == 1) {
// If current element is 1, recursively
// calculate the number of squares and add
// it to the answer
ans += solve(matrix, m, n, i, j);
}
}
}
// Return the final answer
return ans;
} // Driver code int main()
{ vector<vector< int > > arr
= { { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 0 } };
cout << countSquareMatrices(arr);
return 0;
} |
import java.util.ArrayList;
import java.util.List;
public class SquareSubmatrices {
// Function to solve the problem recursively
static int solve(List<List<Integer>> matrix, int m, int n, int i, int j) {
// Base case: if out of bounds or current element is 0
if (i < 0 || i >= m || j < 0 || j >= n || matrix.get(i).get(j) == 0 ) {
return 0 ;
}
// Recursive calls to calculate the number of squares in right, bottom, and bottom-right directions
int right = solve(matrix, m, n, i, j + 1 );
int bottom = solve(matrix, m, n, i + 1 , j);
int bottomRight = solve(matrix, m, n, i + 1 , j + 1 );
// Return the count of squares for the current position
return 1 + Math.min(Math.min(right, bottom), bottomRight);
}
// Function to return the number of square submatrices with all 1s
static int countSquareMatrices(List<List<Integer>> matrix) {
int m = matrix.size();
int n = matrix.get( 0 ).size();
int ans = 0 ;
// Iterate over each element of the matrix
for ( int i = 0 ; i < m; i++) {
for ( int j = 0 ; j < n; j++) {
if (matrix.get(i).get(j) == 1 ) {
// If current element is 1, recursively calculate the number of squares and add it to the answer
ans += solve(matrix, m, n, i, j);
}
}
}
// Return the final answer
return ans;
}
// Driver code
public static void main(String[] args) {
List<List<Integer>> arr = new ArrayList<>();
arr.add(List.of( 1 , 0 , 1 ));
arr.add(List.of( 1 , 1 , 0 ));
arr.add(List.of( 1 , 1 , 0 ));
System.out.println(countSquareMatrices(arr));
}
} |
def solve(matrix, m, n, i, j):
# Base case: if out of bounds or current element is 0
if i < 0 or i > = m or j < 0 or j > = n or matrix[i][j] = = 0 :
return 0
# Recursive calls to calculate the number of squares in right, bottom, and bottom-right directions
right = solve(matrix, m, n, i, j + 1 )
bottom = solve(matrix, m, n, i + 1 , j)
bottom_right = solve(matrix, m, n, i + 1 , j + 1 )
# Return the count of squares for the current position
return 1 + min (right, bottom, bottom_right)
def countSquareMatrices(matrix):
m = len (matrix)
n = len (matrix[ 0 ])
ans = 0
# Iterate over each element of the matrix
for i in range (m):
for j in range (n):
if matrix[i][j] = = 1 :
# If current element is 1, recursively calculate the number of squares and add it to the answer
ans + = solve(matrix, m, n, i, j)
# Return the final answer
return ans
# Driver code arr = [[ 1 , 0 , 1 ], [ 1 , 1 , 0 ], [ 1 , 1 , 0 ]]
print (countSquareMatrices(arr))
|
using System;
using System.Collections.Generic;
public class GFG
{ // Function to solve the problem recursively
public static int Solve(List<List< int >> matrix, int m, int n, int i, int j)
{
// Base case: if out of bounds or current element is 0
if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] == 0)
{
return 0;
}
// Recursive calls to calculate the number of squares in
// right, bottom, and bottom-right directions
int right = Solve(matrix, m, n, i, j + 1);
int bottom = Solve(matrix, m, n, i + 1, j);
int bottom_right = Solve(matrix, m, n, i + 1, j + 1);
// Return the count of squares for the current position
return 1 + Math.Min(Math.Min(right, bottom), bottom_right);
}
// Function to return the number of square submatrices with all 1s
public static int CountSquareMatrices(List<List< int >> matrix)
{
int m = matrix.Count;
int n = matrix[0].Count;
int ans = 0;
// Iterate over each element of the matrix
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
{
if (matrix[i][j] == 1)
{
// If current element is 1, recursively calculate
// the number of squares and add it to the answer
ans += Solve(matrix, m, n, i, j);
}
}
}
// Return the final answer
return ans;
}
// Driver code
public static void Main( string [] args)
{
List<List< int >> arr = new List<List< int >>()
{
new List< int >() { 1, 0, 1 },
new List< int >() { 1, 1, 0 },
new List< int >() { 1, 1, 0 }
};
Console.WriteLine(CountSquareMatrices(arr));
}
} |
<script> // JavaScript program to return the number of // square submatrices with all 1s // Function to solve the problem recursively function solve(matrix, m, n, i, j) {
// Base case: if out of bounds or current element is 0
if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] === 0) {
return 0;
}
// Recursive calls to calculate the number of squares in
// right, bottom, and bottom-right directions
const right = solve(matrix, m, n, i, j + 1);
const bottom = solve(matrix, m, n, i + 1, j);
const bottom_right = solve(matrix, m, n, i + 1, j + 1);
// Return the count of squares for the current position
return 1 + Math.min(right, bottom, bottom_right);
} // Function to return the number of square submatrices with // all 1s function countSquareMatrices(matrix) {
const m = matrix.length;
const n = matrix[0].length;
let ans = 0;
// Iterate over each element of the matrix
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (matrix[i][j] === 1) {
// If current element is 1, recursively
// calculate the number of squares and add
// it to the answer
ans += solve(matrix, m, n, i, j);
}
}
}
// Return the final answer
return ans;
} // Driver code const arr = [ [1, 0, 1],
[1, 1, 0],
[1, 1, 0]
]; document.write(countSquareMatrices(arr)); // This code is contributed by Susobhan Akhuli </script> |
7
Time Complexity: O(2N*M)
Auxiliary Space: O(1)
An approach using Top Down DP/ Memoization:
Memoization is used in this problem to optimize the solution by avoiding redundant calculations. Since we are making recursive calls to solve subproblems, there can be overlapping subproblems where the same submatrix is being computed multiple times. By using memoization, we can store the results of subproblems in a table (in this case, the dp table) and reuse them when needed. When a subproblem is encountered again, instead of recomputing its value, we can simply retrieve it from the table. This greatly reduces the number of redundant calculations and improves the overall efficiency of the algorithm.
In the provided code, the dp table is a 2D vector that stores the computed results for each position in the matrix. Before making a recursive call, the function checks if the value for the current position is already present in the dp table. If so, it directly returns that value instead of recomputing it.
Using memoization ensures that each subproblem is solved only once, leading to a significant reduction in the number of recursive calls and improving the overall time complexity of the solution.
Below is the implemenation of the above approach:
// C++ program to return the number of // square submatrices with all 1s #include <bits/stdc++.h> using namespace std;
// Recursive function to solve the problem int solve(vector<vector< int > >& matrix, int m, int n, int i,
int j, vector<vector< int > >& dp)
{ // Base case: if out of bounds or current element is 0
if (i < 0 || i >= m || j < 0 || j >= n
|| matrix[i][j] == 0) {
return 0;
}
// If the value is already calculated, return it from dp
// table
if (dp[i][j] != -1)
return dp[i][j];
// Recursive calls to calculate the number of squares in
// right, bottom, and bottom-right directions
int right = solve(matrix, m, n, i, j + 1, dp);
int bottom = solve(matrix, m, n, i + 1, j, dp);
int bottom_right
= solve(matrix, m, n, i + 1, j + 1, dp);
// Memoize the calculated value and return it
return dp[i][j]
= 1 + min({ right, bottom, bottom_right });
} // Function to return the number of square submatrices with // all 1s int countSquareMatrices(vector<vector< int > >& matrix)
{ int m = matrix.size();
int n = matrix[0].size();
// Create a dp table to store the results of subproblems
vector<vector< int > > dp(m + 1, vector< int >(n + 1, -1));
int ans = 0;
// Iterate over each element of the matrix
for ( int i = 0; i < m; i++) {
for ( int j = 0; j < n; j++) {
if (matrix[i][j] == 1) {
// If the current element is 1, recursively
// calculate the number of squares and add
// it to the answer
ans += solve(matrix, m, n, i, j, dp);
}
}
}
// Return the final answer
return ans;
} // Driver code int main()
{ vector<vector< int > > arr
= { { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 0 } };
cout << countSquareMatrices(arr);
return 0;
} |
import java.util.*;
public class SquareSubmatrices {
// Recursive function to solve the problem
static int solve( int [][] matrix, int m, int n, int i,
int j, int [][] dp)
{
// Base case: if out of bounds or current element is
// 0
if (i < 0 || i >= m || j < 0 || j >= n
|| matrix[i][j] == 0 ) {
return 0 ;
}
// If the value is already calculated, return it
// from dp table
if (dp[i][j] != - 1 )
return dp[i][j];
// Recursive calls to calculate the number of
// squares in right, bottom, and bottom-right
// directions
int right = solve(matrix, m, n, i, j + 1 , dp);
int bottom = solve(matrix, m, n, i + 1 , j, dp);
int bottomRight
= solve(matrix, m, n, i + 1 , j + 1 , dp);
// Memoize the calculated value and return it
return dp[i][j]
= 1
+ Math.min(Math.min(right, bottom),
bottomRight);
}
// Function to return the number of square submatrices
// with all 1s
static int countSquareMatrices( int [][] matrix)
{
int m = matrix.length;
int n = matrix[ 0 ].length;
// Create a dp table to store the results of
// subproblems
int [][] dp = new int [m + 1 ][n + 1 ];
for ( int [] row : dp) {
Arrays.fill(row, - 1 );
}
int ans = 0 ;
// Iterate over each element of the matrix
for ( int i = 0 ; i < m; i++) {
for ( int j = 0 ; j < n; j++) {
if (matrix[i][j] == 1 ) {
// If the current element is 1,
// recursively calculate the number of
// squares and add it to the answer
ans += solve(matrix, m, n, i, j, dp);
}
}
}
// Return the final answer
return ans;
}
// Driver code
public static void main(String[] args)
{
int [][] arr
= { { 1 , 0 , 1 }, { 1 , 1 , 0 }, { 1 , 1 , 0 } };
System.out.println(countSquareMatrices(arr));
}
} |
# Recursive function to solve the problem def solve(matrix, m, n, i, j, dp):
# Base case: if out of bounds or current element is 0
if i < 0 or i > = m or j < 0 or j > = n or matrix[i][j] = = 0 :
return 0
# If the value is already calculated, return it from dp table
if dp[i][j] ! = - 1 :
return dp[i][j]
# Recursive calls to calculate the number of squares in right, bottom, and bottom-right directions
right = solve(matrix, m, n, i, j + 1 , dp)
bottom = solve(matrix, m, n, i + 1 , j, dp)
bottom_right = solve(matrix, m, n, i + 1 , j + 1 , dp)
# Memoize the calculated value and return it
dp[i][j] = 1 + min (right, bottom, bottom_right)
return dp[i][j]
# Function to return the number of square submatrices with all 1s def countSquareMatrices(matrix):
m = len (matrix)
n = len (matrix[ 0 ])
# Create a dp table to store the results of subproblems
dp = [[ - 1 ] * (n + 1 ) for _ in range (m + 1 )]
ans = 0
# Iterate over each element of the matrix
for i in range (m):
for j in range (n):
if matrix[i][j] = = 1 :
# If the current element is 1, recursively calculate the number of squares and add it to the answer
ans + = solve(matrix, m, n, i, j, dp)
# Return the final answer
return ans
# Driver code arr = [[ 1 , 0 , 1 ], [ 1 , 1 , 0 ], [ 1 , 1 , 0 ]]
print (countSquareMatrices(arr))
|
using System;
public class GFG
{ // Recursive function to solve the problem
public static int Solve( int [][] matrix, int m, int n, int i, int j, int [][] dp)
{
// Base case: if out of bounds or current element is 0
if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] == 0)
{
return 0;
}
// If the value is already calculated, return it from dp table
if (dp[i][j] != -1)
return dp[i][j];
// Recursive calls to calculate the number of squares in right,
// bottom, and bottom-right directions
int right = Solve(matrix, m, n, i, j + 1, dp);
int bottom = Solve(matrix, m, n, i + 1, j, dp);
int bottomRight = Solve(matrix, m, n, i + 1, j + 1, dp);
// Memoize the calculated value and return it
return dp[i][j] = 1 + Math.Min(right, Math.Min(bottom, bottomRight));
}
// Function to return the number of square submatrices with all 1s
public static int CountSquareMatrices( int [][] matrix)
{
int m = matrix.Length;
int n = matrix[0].Length;
// Create a dp table to store the results of subproblems
int [][] dp = new int [m + 1][];
for ( int i = 0; i <= m; i++)
{
dp[i] = new int [n + 1];
for ( int j = 0; j <= n; j++)
{
dp[i][j] = -1;
}
}
int ans = 0;
// Iterate over each element of the matrix
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
{
if (matrix[i][j] == 1)
{
// If the current element is 1, recursively
// calculate the number of squares and add it to the answer
ans += Solve(matrix, m, n, i, j, dp);
}
}
}
// Return the final answer
return ans;
}
// Driver code
public static void Main( string [] args)
{
int [][] arr = new int [][] {
new int [] { 1, 0, 1 },
new int [] { 1, 1, 0 },
new int [] { 1, 1, 0 }
};
Console.WriteLine(CountSquareMatrices(arr));
}
} |
// Recursive function to solve the problem function solve(matrix, m, n, i, j, dp) {
// Base case: if out of bounds or current element is 0
if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] === 0) {
return 0;
}
// If the value is already calculated, return it from dp table
if (dp[i][j] !== -1) {
return dp[i][j];
}
// Recursive calls to calculate the number of squares in
// right, bottom, and bottom-right directions
const right = solve(matrix, m, n, i, j + 1, dp);
const bottom = solve(matrix, m, n, i + 1, j, dp);
const bottomRight = solve(matrix, m, n, i + 1, j + 1, dp);
// Memoize the calculated value and return it
return (dp[i][j] = 1 + Math.min(right, bottom, bottomRight));
} // Function to return the number of square submatrices with all 1s function countSquareMatrices(matrix) {
const m = matrix.length;
const n = matrix[0].length;
// Create a dp table to store the results of subproblems
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(-1));
let ans = 0;
// Iterate over each element of the matrix
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (matrix[i][j] === 1) {
// If the current element is 1, recursively
// calculate the number of squares and add
// it to the answer
ans += solve(matrix, m, n, i, j, dp);
}
}
}
// Return the final answer
return ans;
} // Example usage const matrix = [ [1, 0, 1],
[1, 1, 0],
[1, 1, 0],
]; console.log(countSquareMatrices(matrix)); |
7
Time Complexity: O(N*M)
Auxiliary Space: O(1)
An approach using Buttom-Up:
This problem can be solved using Dynamic Programming.
- Let the array arr[i][j] store the number of square matrices ending at (i, j)
-
The recurrence relation to find the number of squares ending at (i, j) can be given by:
-
If arr[i][j] is 1:
- arr[i][j] = min( min(arr[i-1][j], arr[i][j-1]), arr[i-1][j-1]) + 1
-
Else if arr[i][j] is 0:
- arr[i][j] = 0
-
If arr[i][j] is 1:
- Calculate the sum of the array which is equal to the number of square submatrices with all 1s.
Below is the implementation of the above approach:
// C++ program to return the number of // square submatrices with all 1s #include <bits/stdc++.h> using namespace std;
#define n 3 #define m 3 // Function to return the number of // square submatrices with all 1s int countSquareMatrices( int a[][m],
int N, int M)
{ // Initialize count variable
int count = 0;
for ( int i = 1; i < N; i++) {
for ( int j = 1; j < M; j++) {
// If a[i][j] is equal to 0
if (a[i][j] == 0)
continue ;
// Calculate number of
// square submatrices
// ending at (i, j)
a[i][j] = min(min(a[i - 1][j],
a[i][j - 1]),
a[i - 1][j - 1])
+ 1;
}
}
// Calculate the sum of the array
for ( int i = 0; i < N; i++)
for ( int j = 0; j < M; j++)
count += a[i][j];
return count;
} // Driver code int main()
{ int arr[][m] = { { 1, 0, 1 },
{ 1, 1, 0 },
{ 1, 1, 0 } };
cout << countSquareMatrices(arr, n, m);
return 0;
} |
// Java program to return the number of // square submatrices with all 1s class GFG
{ final static int n = 3 ;
final static int m = 3 ;
// Function to return the number of
// square submatrices with all 1s
static int countSquareMatrices( int a[][], int N, int M)
{
// Initialize count variable
int count = 0 ;
for ( int i = 1 ; i < N; i++)
{
for ( int j = 1 ; j < M; j++)
{
// If a[i][j] is equal to 0
if (a[i][j] == 0 )
continue ;
// Calculate number of
// square submatrices
// ending at (i, j)
a[i][j] = Math.min(Math.min(a[i - 1 ][j], a[i][j - 1 ]),
a[i - 1 ][j - 1 ]) + 1 ;
}
}
// Calculate the sum of the array
for ( int i = 0 ; i < N; i++)
for ( int j = 0 ; j < M; j++)
count += a[i][j];
return count;
}
// Driver code
public static void main (String[] args)
{
int arr[][] = { { 1 , 0 , 1 },
{ 1 , 1 , 0 },
{ 1 , 1 , 0 } };
System.out.println(countSquareMatrices(arr, n, m));
}
} // This code is contributed by AnkitRai01 |
# Python3 program to return the number of # square submatrices with all 1s n = 3
m = 3
# Function to return the number of # square submatrices with all 1s def countSquareMatrices(a, N, M):
# Initialize count variable
count = 0
for i in range ( 1 , N):
for j in range ( 1 , M):
# If a[i][j] is equal to 0
if (a[i][j] = = 0 ):
continue
# Calculate number of
# square submatrices
# ending at (i, j)
a[i][j] = min ([a[i - 1 ][j],
a[i][j - 1 ], a[i - 1 ][j - 1 ]]) + 1
# Calculate the sum of the array
for i in range (N):
for j in range (M):
count + = a[i][j]
return count
# Driver code arr = [ [ 1 , 0 , 1 ],
[ 1 , 1 , 0 ],
[ 1 , 1 , 0 ] ]
print (countSquareMatrices(arr, n, m))
# This code is contributed by mohit kumar 29 |
// C# program to return the number of // square submatrices with all 1s using System;
class GFG
{ static int n = 3;
static int m = 3;
// Function to return the number of
// square submatrices with all 1s
static int countSquareMatrices( int [,]a, int N, int M)
{
// Initialize count variable
int count = 0;
for ( int i = 1; i < N; i++)
{
for ( int j = 1; j < M; j++)
{
// If a[i][j] is equal to 0
if (a[i, j] == 0)
continue ;
// Calculate number of
// square submatrices
// ending at (i, j)
a[i, j] = Math.Min(Math.Min(a[i - 1, j], a[i, j - 1]),
a[i - 1, j - 1]) + 1;
}
}
// Calculate the sum of the array
for ( int i = 0; i < N; i++)
for ( int j = 0; j < M; j++)
count += a[i, j];
return count;
}
// Driver code
public static void Main()
{
int [,]arr = { { 1, 0, 1 },
{ 1, 1, 0 },
{ 1, 1, 0 } };
Console.WriteLine(countSquareMatrices(arr, n, m));
}
} // This code is contributed by AnkitRai01 |
<script> // Javascript program to return the number of // square submatrices with all 1s var n = 3
var m = 3
// Function to return the number of // square submatrices with all 1s function countSquareMatrices(a, N, M)
{ // Initialize count variable
var count = 0;
for ( var i = 1; i < N; i++) {
for ( var j = 1; j < M; j++) {
// If a[i][j] is equal to 0
if (a[i][j] == 0)
continue ;
// Calculate number of
// square submatrices
// ending at (i, j)
a[i][j] = Math.min(Math.min(a[i - 1][j],
a[i][j - 1]),
a[i - 1][j - 1])
+ 1;
}
}
// Calculate the sum of the array
for ( var i = 0; i < N; i++)
for ( var j = 0; j < M; j++)
count += a[i][j];
return count;
} // Driver code var arr = [ [ 1, 0, 1 ],
[ 1, 1, 0 ],
[ 1, 1, 0 ] ];
document.write( countSquareMatrices(arr, n, m)); </script> |
7
Time Complexity: O(N*M)
Auxiliary Space: O(1)