Number of submatrices with OR value 1
Given a N*N binary matrix, the task is to find the count of rectangular sub-matrices with OR value 1.
Examples:
Input : arr[][] = {{0, 0, 0},
{0, 0, 0},
{0, 0, 0}}
Output : 0
Explanation: All the submatrices will have an OR value 0.
Thus, ans = 0.
Input : arr[][] = {{0, 0, 0},
{0, 1, 0},
{0, 0, 0}}
Output : 16
A Simple Solution will be to generate all the possible sub-matrices and then check if any of the values inside them are 1. If for a sub-matrix, at least a single element is one, we increment the value of the final answer for one. The time complexity of the above approach is O(n6).
Better approach: Let’s have a look at this problem in another way. We will now try to find the number of submatrices with all 0s. And for the final answer, we will subtract this value from the total number of submatrices.
To optimize the process, for every index of the matrix, we will try to find the number of submatrices starting from that index having all 0s in it.
Our first step towards solving this problem is creating a matrix ‘p_arr’.
- For each index (R, C), if arr[R][C] equals 0, then in p_arr[R][C], we will store the number of 0s to the right of the cell(R, C) along row ‘R’ before we encounter ‘1’ or end of the array plus one.
- If arr[R][C] equals 1, the p_arr[R][C] equals zero.
For creating this matrix, we will use the following recurrence relation.
IF arr[R][C] is 0
p_arr[R][C] = p_arr[R][C+1] + 1
ELSE
p_arr[R][C] = 0
arr[][] = {{1, 0, 0, 0},
{0, 1, 0, 1},
{0, 1, 0, 0},
{0, 0, 0, 0}}
p_arr[][] for above will look like
{{0, 3, 2, 1},
{1, 0, 1, 0},
{1, 0, 2, 1},
{4, 3, 2, 1}}
Once, we have the required matrix p_arr, we will start processing the matrix ‘p_arr’ column-wise. If we are processing the jth column of the matrix ‘p_arr’, then for each element ‘i’ of this column, we will try to find the number of sub-matrices starting from the cell (i, j) with all 0s.
For this, we can use the stack data structure.
Algorithm:
- Initialize a stack ‘q’ to store the value of the elements getting pushed along with the count(Cij) of the number of elements that were pushed in the stack with a value strictly greater than the value of the current element. We will use pairs to tie up the two data together.
Initialize a variable to_sum with 0. At each step, this variable is updated to store the number of submatrices with all 0s starting from the element being pushed at that step. Thus, using ‘to_sum’, we update the count of the number of submatrices with all 0s at each step.
- For a column ‘j’, at any step ‘i’, we will prepare to push p_arr[i][j] in the stack. Let Qt represent the topmost element of the stack and Ct represent the number of elements previously pushed in the stack with a value greater than the top-most element of the stack. Before pushing an element ‘p_arr[i][j]’ in the stack, while the stack is not empty or topmost element is greater than the number to be pushed, keep popping the topmost element of the stack and at the same time update to_sum as to_sum += (Ct + 1) * (Qt – p_arr[i][j]). Let Ci, j represent the number of elements greater than the current element that was pushed in this stack previously. We also need to keep a track of Ci, j. Thus, before popping an element, we update Ci, j as Ci, j += Ct along with to_sum.
- We update the number of submatrices with all zeros as count_zero_submatrices += to_sum.
- Finally, we push that element in the stack after pairing it with Ci, j.
The total number of sub-matrices in a N*N matrix equals:
(N2 * (N + 1)2)/4
Thus, the final answer will be:
ans = (N2 * (N + 1)2)/4 - count_zero_submatrices
We create the prefix-array in O(N2) and for each column, we push an element in the stack or pop it out only once. Thus, the time complexity of this algorithm is O(N2).
Below is the implementation of the above approach:
C++
#include <iostream>
#include <stack>
#define n 3
using namespace std;
void findPrefixCount( int p_arr[][n], bool arr[][n])
{
for ( int i = 0; i < n; i++)
for ( int j = n - 1; j >= 0; j--) {
if (arr[i][j])
continue ;
if (j != n - 1)
p_arr[i][j] += p_arr[i][j + 1];
p_arr[i][j] += ( int )(!arr[i][j]);
}
}
int matrixOrValueOne( bool arr[][n])
{
int p_arr[n][n] = { 0 };
findPrefixCount(p_arr, arr);
int count_zero_submatrices = 0;
for ( int j = 0; j < n; j++) {
int i = n - 1;
stack<pair< int , int > > q;
int to_sum = 0;
while (i >= 0) {
int c = 0;
while (q.size() != 0 and q.top().first > p_arr[i][j]) {
to_sum -= (q.top().second + 1) *
(q.top().first - p_arr[i][j]);
c += q.top().second + 1;
q.pop();
}
to_sum += p_arr[i][j];
count_zero_submatrices += to_sum;
q.push({ p_arr[i][j], c });
i--;
}
}
return (n * (n + 1) * n * (n + 1)) / 4
- count_zero_submatrices;
}
int main()
{
bool arr[][n] = { { 0, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 0 } };
cout << matrixOrValueOne(arr);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int n = 3 ;
static class pair
{
int first, second;
public pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
static void findPrefixCount( int p_arr[][],
boolean arr[][])
{
for ( int i = 0 ; i < n; i++)
for ( int j = n - 1 ; j >= 0 ; j--)
{
if (arr[i][j])
continue ;
if (j != n - 1 )
p_arr[i][j] += p_arr[i][j + 1 ];
p_arr[i][j] += (arr[i][j] == false ? 1 : 0 );
}
}
static int matrixOrValueOne( boolean arr[][])
{
int [][]p_arr = new int [n][n];
findPrefixCount(p_arr, arr);
int count_zero_submatrices = 0 ;
for ( int j = 0 ; j < n; j++)
{
int i = n - 1 ;
Stack<pair> q = new Stack<pair>();
int to_sum = 0 ;
while (i >= 0 )
{
int c = 0 ;
while (q.size() != 0 &&
q.peek().first > p_arr[i][j])
{
to_sum -= (q.peek().second + 1 ) *
(q.peek().first - p_arr[i][j]);
c += q.peek().second + 1 ;
q.pop();
}
to_sum += p_arr[i][j];
count_zero_submatrices += to_sum;
q.add( new pair(p_arr[i][j], c ));
i--;
}
}
return (n * (n + 1 ) * n * (n + 1 )) / 4
- count_zero_submatrices;
}
public static void main(String[] args)
{
boolean arr[][] = { { false , false , false },
{ false , true , false },
{ false , false , false } };
System.out.println(matrixOrValueOne(arr));
}
}
|
Python3
def findPrefixCount(p_arr, arr):
for i in range ( 0 , n):
for j in range (n - 1 , - 1 , - 1 ):
if arr[i][j]:
continue
if j ! = n - 1 :
p_arr[i][j] + = p_arr[i][j + 1 ]
p_arr[i][j] + = int ( not arr[i][j])
def matrixOrValueOne(arr):
p_arr = [[ 0 for i in range (n)]
for j in range (n)]
findPrefixCount(p_arr, arr)
count_zero_submatrices = 0
for j in range ( 0 , n):
i = n - 1
q = []
to_sum = 0
while i > = 0 :
c = 0
while ( len (q) ! = 0 and
q[ - 1 ][ 0 ] > p_arr[i][j]):
to_sum - = ((q[ - 1 ][ 1 ] + 1 ) *
(q[ - 1 ][ 0 ] - p_arr[i][j]))
c + = q.pop()[ 1 ] + 1
to_sum + = p_arr[i][j]
count_zero_submatrices + = to_sum
q.append((p_arr[i][j], c))
i - = 1
return ((n * (n + 1 ) * n * (n + 1 )) / /
4 - count_zero_submatrices)
if __name__ = = "__main__" :
n = 3
arr = [[ 0 , 0 , 0 ],
[ 0 , 1 , 0 ],
[ 0 , 0 , 0 ]]
print (matrixOrValueOne(arr))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int n = 3;
class pair
{
public int first, second;
public pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
static void findPrefixCount( int [,]p_arr,
bool [,]arr)
{
for ( int i = 0; i < n; i++)
for ( int j = n - 1; j >= 0; j--)
{
if (arr[i, j])
continue ;
if (j != n - 1)
p_arr[i, j] += p_arr[i, j + 1];
p_arr[i, j] += (arr[i, j] == false ? 1 : 0);
}
}
static int matrixOrValueOne( bool [,]arr)
{
int [,]p_arr = new int [n, n];
findPrefixCount(p_arr, arr);
int count_zero_submatrices = 0;
for ( int j = 0; j < n; j++)
{
int i = n - 1;
Stack<pair> q = new Stack<pair>();
int to_sum = 0;
while (i >= 0)
{
int c = 0;
while (q.Count != 0 &&
q.Peek().first > p_arr[i, j])
{
to_sum -= (q.Peek().second + 1) *
(q.Peek().first - p_arr[i, j]);
c += q.Peek().second + 1;
q.Pop();
}
to_sum += p_arr[i, j];
count_zero_submatrices += to_sum;
q.Push( new pair(p_arr[i, j], c));
i--;
}
}
return (n * (n + 1) * n * (n + 1)) / 4 -
count_zero_submatrices;
}
public static void Main(String[] args)
{
bool [,]arr = { { false , false , false },
{ false , true , false },
{ false , false , false } };
Console.WriteLine(matrixOrValueOne(arr));
}
}
|
Javascript
<script>
var n = 3
function findPrefixCount(p_arr, arr)
{
for ( var i = 0; i < n; i++)
for ( var j = n - 1; j >= 0; j--) {
if (arr[i][j])
continue ;
if (j != n - 1)
p_arr[i][j] += p_arr[i][j + 1];
p_arr[i][j] += (!arr[i][j]);
}
}
function matrixOrValueOne(arr)
{
var p_arr = Array.from(Array(n), ()=> Array(n).fill(0));
findPrefixCount(p_arr, arr);
var count_zero_submatrices = 0;
for ( var j = 0; j < n; j++) {
var i = n - 1;
var q = [];
var to_sum = 0;
while (i >= 0) {
var c = 0;
while (q.length != 0 && q[q.length-1][0] > p_arr[i][j]) {
to_sum -= (q[q.length-1][1] + 1) *
(q[q.length-1][0] - p_arr[i][j]);
c += q[q.length-1][1] + 1;
q.pop();
}
to_sum += p_arr[i][j];
count_zero_submatrices += to_sum;
q.push([p_arr[i][j], c]);
i--;
}
}
return (n * (n + 1) * n * (n + 1)) / 4
- count_zero_submatrices;
}
var arr = [ [ 0, 0, 0 ],
[ 0, 1, 0 ],
[ 0, 0, 0 ] ];
document.write( matrixOrValueOne(arr));
</script>
|
Time Complexity: O(n2)
Auxiliary Space: O(n2)
Last Updated :
22 Jun, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...