Number of square matrices with all 1s
Last Updated :
07 Dec, 2023
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++
#include <bits/stdc++.h>
using namespace std;
int solve(vector<vector< int > >& matrix, int m, int n, int i,
int j)
{
if (i < 0 or i >= m or j < 0 or j >= n
or matrix[i][j] == 0) {
return 0;
}
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 1 + min({ right, bottom, bottom_right });
}
int countSquareMatrices(vector<vector< int > >& matrix)
{
int m = matrix.size();
int n = matrix[0].size();
int ans = 0;
for ( int i = 0; i < m; i++) {
for ( int j = 0; j < n; j++) {
if (matrix[i][j] == 1) {
ans += solve(matrix, m, n, i, j);
}
}
}
return ans;
}
int main()
{
vector<vector< int > > arr
= { { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 0 } };
cout << countSquareMatrices(arr);
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.List;
public class SquareSubmatrices {
static int solve(List<List<Integer>> matrix, int m, int n, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n || matrix.get(i).get(j) == 0 ) {
return 0 ;
}
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 1 + Math.min(Math.min(right, bottom), bottomRight);
}
static int countSquareMatrices(List<List<Integer>> matrix) {
int m = matrix.size();
int n = matrix.get( 0 ).size();
int ans = 0 ;
for ( int i = 0 ; i < m; i++) {
for ( int j = 0 ; j < n; j++) {
if (matrix.get(i).get(j) == 1 ) {
ans += solve(matrix, m, n, i, j);
}
}
}
return ans;
}
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));
}
}
|
Python3
def solve(matrix, m, n, i, j):
if i < 0 or i > = m or j < 0 or j > = n or matrix[i][j] = = 0 :
return 0
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 1 + min (right, bottom, bottom_right)
def countSquareMatrices(matrix):
m = len (matrix)
n = len (matrix[ 0 ])
ans = 0
for i in range (m):
for j in range (n):
if matrix[i][j] = = 1 :
ans + = solve(matrix, m, n, i, j)
return ans
arr = [[ 1 , 0 , 1 ], [ 1 , 1 , 0 ], [ 1 , 1 , 0 ]]
print (countSquareMatrices(arr))
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
public static int Solve(List<List< int >> matrix, int m, int n, int i, int j)
{
if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] == 0)
{
return 0;
}
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 1 + Math.Min(Math.Min(right, bottom), bottom_right);
}
public static int CountSquareMatrices(List<List< int >> matrix)
{
int m = matrix.Count;
int n = matrix[0].Count;
int ans = 0;
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
{
if (matrix[i][j] == 1)
{
ans += Solve(matrix, m, n, i, j);
}
}
}
return ans;
}
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));
}
}
|
Javascript
<script>
function solve(matrix, m, n, i, j) {
if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] === 0) {
return 0;
}
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 1 + Math.min(right, bottom, bottom_right);
}
function countSquareMatrices(matrix) {
const m = matrix.length;
const n = matrix[0].length;
let ans = 0;
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (matrix[i][j] === 1) {
ans += solve(matrix, m, n, i, j);
}
}
}
return ans;
}
const arr = [
[1, 0, 1],
[1, 1, 0],
[1, 1, 0]
];
document.write(countSquareMatrices(arr));
</script>
|
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++
#include <bits/stdc++.h>
using namespace std;
int solve(vector<vector< int > >& matrix, int m, int n, int i,
int j, vector<vector< int > >& dp)
{
if (i < 0 || i >= m || j < 0 || j >= n
|| matrix[i][j] == 0) {
return 0;
}
if (dp[i][j] != -1)
return dp[i][j];
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);
return dp[i][j]
= 1 + min({ right, bottom, bottom_right });
}
int countSquareMatrices(vector<vector< int > >& matrix)
{
int m = matrix.size();
int n = matrix[0].size();
vector<vector< int > > dp(m + 1, vector< int >(n + 1, -1));
int ans = 0;
for ( int i = 0; i < m; i++) {
for ( int j = 0; j < n; j++) {
if (matrix[i][j] == 1) {
ans += solve(matrix, m, n, i, j, dp);
}
}
}
return ans;
}
int main()
{
vector<vector< int > > arr
= { { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 0 } };
cout << countSquareMatrices(arr);
return 0;
}
|
Java
import java.util.*;
public class SquareSubmatrices {
static int solve( int [][] matrix, int m, int n, int i,
int j, int [][] dp)
{
if (i < 0 || i >= m || j < 0 || j >= n
|| matrix[i][j] == 0 ) {
return 0 ;
}
if (dp[i][j] != - 1 )
return dp[i][j];
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);
return dp[i][j]
= 1
+ Math.min(Math.min(right, bottom),
bottomRight);
}
static int countSquareMatrices( int [][] matrix)
{
int m = matrix.length;
int n = matrix[ 0 ].length;
int [][] dp = new int [m + 1 ][n + 1 ];
for ( int [] row : dp) {
Arrays.fill(row, - 1 );
}
int ans = 0 ;
for ( int i = 0 ; i < m; i++) {
for ( int j = 0 ; j < n; j++) {
if (matrix[i][j] == 1 ) {
ans += solve(matrix, m, n, i, j, dp);
}
}
}
return ans;
}
public static void main(String[] args)
{
int [][] arr
= { { 1 , 0 , 1 }, { 1 , 1 , 0 }, { 1 , 1 , 0 } };
System.out.println(countSquareMatrices(arr));
}
}
|
Python3
def solve(matrix, m, n, i, j, dp):
if i < 0 or i > = m or j < 0 or j > = n or matrix[i][j] = = 0 :
return 0
if dp[i][j] ! = - 1 :
return dp[i][j]
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)
dp[i][j] = 1 + min (right, bottom, bottom_right)
return dp[i][j]
def countSquareMatrices(matrix):
m = len (matrix)
n = len (matrix[ 0 ])
dp = [[ - 1 ] * (n + 1 ) for _ in range (m + 1 )]
ans = 0
for i in range (m):
for j in range (n):
if matrix[i][j] = = 1 :
ans + = solve(matrix, m, n, i, j, dp)
return ans
arr = [[ 1 , 0 , 1 ], [ 1 , 1 , 0 ], [ 1 , 1 , 0 ]]
print (countSquareMatrices(arr))
|
C#
using System;
public class GFG
{
public static int Solve( int [][] matrix, int m, int n, int i, int j, int [][] dp)
{
if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] == 0)
{
return 0;
}
if (dp[i][j] != -1)
return dp[i][j];
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);
return dp[i][j] = 1 + Math.Min(right, Math.Min(bottom, bottomRight));
}
public static int CountSquareMatrices( int [][] matrix)
{
int m = matrix.Length;
int n = matrix[0].Length;
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;
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
{
if (matrix[i][j] == 1)
{
ans += Solve(matrix, m, n, i, j, dp);
}
}
}
return ans;
}
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));
}
}
|
Javascript
function solve(matrix, m, n, i, j, dp) {
if (i < 0 || i >= m || j < 0 || j >= n || matrix[i][j] === 0) {
return 0;
}
if (dp[i][j] !== -1) {
return dp[i][j];
}
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);
return (dp[i][j] = 1 + Math.min(right, bottom, bottomRight));
}
function countSquareMatrices(matrix) {
const m = matrix.length;
const n = matrix[0].length;
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(-1));
let ans = 0;
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (matrix[i][j] === 1) {
ans += solve(matrix, m, n, i, j, dp);
}
}
}
return ans;
}
const matrix = [
[1, 0, 1],
[1, 1, 0],
[1, 1, 0],
];
console.log(countSquareMatrices(matrix));
|
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:
- 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:
CPP
#include <bits/stdc++.h>
using namespace std;
#define n 3
#define m 3
int countSquareMatrices( int a[][m],
int N, int M)
{
int count = 0;
for ( int i = 1; i < N; i++) {
for ( int j = 1; j < M; j++) {
if (a[i][j] == 0)
continue ;
a[i][j] = min(min(a[i - 1][j],
a[i][j - 1]),
a[i - 1][j - 1])
+ 1;
}
}
for ( int i = 0; i < N; i++)
for ( int j = 0; j < M; j++)
count += a[i][j];
return count;
}
int main()
{
int arr[][m] = { { 1, 0, 1 },
{ 1, 1, 0 },
{ 1, 1, 0 } };
cout << countSquareMatrices(arr, n, m);
return 0;
}
|
Java
class GFG
{
final static int n = 3 ;
final static int m = 3 ;
static int countSquareMatrices( int a[][], int N, int M)
{
int count = 0 ;
for ( int i = 1 ; i < N; i++)
{
for ( int j = 1 ; j < M; j++)
{
if (a[i][j] == 0 )
continue ;
a[i][j] = Math.min(Math.min(a[i - 1 ][j], a[i][j - 1 ]),
a[i - 1 ][j - 1 ]) + 1 ;
}
}
for ( int i = 0 ; i < N; i++)
for ( int j = 0 ; j < M; j++)
count += a[i][j];
return count;
}
public static void main (String[] args)
{
int arr[][] = { { 1 , 0 , 1 },
{ 1 , 1 , 0 },
{ 1 , 1 , 0 } };
System.out.println(countSquareMatrices(arr, n, m));
}
}
|
Python
n = 3
m = 3
def countSquareMatrices(a, N, M):
count = 0
for i in range ( 1 , N):
for j in range ( 1 , M):
if (a[i][j] = = 0 ):
continue
a[i][j] = min ([a[i - 1 ][j],
a[i][j - 1 ], a[i - 1 ][j - 1 ]]) + 1
for i in range (N):
for j in range (M):
count + = a[i][j]
return count
arr = [ [ 1 , 0 , 1 ],
[ 1 , 1 , 0 ],
[ 1 , 1 , 0 ] ]
print (countSquareMatrices(arr, n, m))
|
C#
using System;
class GFG
{
static int n = 3;
static int m = 3;
static int countSquareMatrices( int [,]a, int N, int M)
{
int count = 0;
for ( int i = 1; i < N; i++)
{
for ( int j = 1; j < M; j++)
{
if (a[i, j] == 0)
continue ;
a[i, j] = Math.Min(Math.Min(a[i - 1, j], a[i, j - 1]),
a[i - 1, j - 1]) + 1;
}
}
for ( int i = 0; i < N; i++)
for ( int j = 0; j < M; j++)
count += a[i, j];
return count;
}
public static void Main()
{
int [,]arr = { { 1, 0, 1 },
{ 1, 1, 0 },
{ 1, 1, 0 } };
Console.WriteLine(countSquareMatrices(arr, n, m));
}
}
|
Javascript
<script>
var n = 3
var m = 3
function countSquareMatrices(a, N, M)
{
var count = 0;
for ( var i = 1; i < N; i++) {
for ( var j = 1; j < M; j++) {
if (a[i][j] == 0)
continue ;
a[i][j] = Math.min(Math.min(a[i - 1][j],
a[i][j - 1]),
a[i - 1][j - 1])
+ 1;
}
}
for ( var i = 0; i < N; i++)
for ( var j = 0; j < M; j++)
count += a[i][j];
return count;
}
var arr = [ [ 1, 0, 1 ],
[ 1, 1, 0 ],
[ 1, 1, 0 ] ];
document.write( countSquareMatrices(arr, n, m));
</script>
|
Time Complexity: O(N*M)
Auxiliary Space: O(1)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...