给定一个N * N二进制矩阵,任务是查找OR值为1的矩形子矩阵的计数。
例子:
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
一个简单的解决方案是生成所有可能的子矩阵,然后检查其中的任何值是否为1。如果对于子矩阵,至少单个元素为1,则将最终答案的值增加1。上述方法的时间复杂度为O(n 6 )。
更好的方法:让我们以另一种方式看待这个问题。现在,我们将尝试查找全为0的子矩阵的数量。对于最终答案,我们将从子矩阵总数中减去该值。
为了优化过程,对于矩阵的每个索引,我们将尝试查找从索引中所有值为0的子矩阵的数量。
解决这个问题的第一步是创建一个矩阵“ p_arr”。
- 对于每个索引(R,C),如果arr [R] [C]等于0,则在p_arr [R] [C]中,我们将沿着行在单元格(R,C)的右侧存储0的数目在遇到“ 1”或数组末尾加1之前的“ R”。
- 如果arr [R] [C]等于1,则p_arr [R] [C]等于零。
为了创建此矩阵,我们将使用以下递归关系。
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}}
一旦有了所需的矩阵p_arr ,我们将开始按列处理矩阵’p_arr’。如果我们正在处理矩阵“ p_arr”的第j列,那么对于该列的每个元素“ i”,我们将尝试查找从单元格(i,j)开始的全为0的子矩阵的数量。
为此,我们可以使用堆栈数据结构。
算法:
- 初始化堆栈“ q”以存储被压入的元素的值以及堆栈中被压入的元素数的count(C ij ),其值严格大于当前元素的值。我们将使用对将两个数据捆绑在一起。
将变量to_sum初始化为0。在每个步骤中,都将更新此变量以存储从在该步骤中被压入元素开始为全0的子矩阵数。因此,使用“ to_sum”,我们在每一步将全为0的子矩阵的数目更新为计数。 - 对于列“ j”,在任何步骤“ i”,我们都准备将p_arr [i] [j]压入堆栈。令Q t代表堆栈的最顶部元素,而C t代表先前推入堆栈的元素数量,其值大于堆栈的最顶端元素。在将元素“ p_arr [i] [j]”压入堆栈之前,如果堆栈不为空或最上面的元素大于要压入的数目,请继续弹出堆栈的最上面的元素,同时更新为to_sum等于to_sum + =(C t +1)*(Q t – p_arr [i] [j]) 。令C i,j表示大于在此堆栈中先前推送的当前元素的元素数。我们还需要跟踪C i,j 。因此,弹出一个元素之前,我们更新C I,J为C I,J + = C与to_sum沿吨。
- 我们将全零的子矩阵数更新为count_zero_submatrices + = to_sum。
- 最后,将其与C i,j配对后,将其推入堆栈。
N * N矩阵中子矩阵的总数等于:
(N2 * (N + 1)2)/4
因此,最终答案将是:
ans = (N2 * (N + 1)2)/4 - count_zero_submatrices
我们在O(N 2 )中创建前缀数组,对于每一列,我们将元素压入堆栈或仅弹出一次。因此,该算法的时间复杂度为O(N 2 )。
下面是上述方法的实现:
C++
// C++ program to count number of submatrices
// with OR value 1
#include
#include
#define n 3
using namespace std;
// Function to find required prefix-count for each row
// from right to left
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]);
}
}
// Function to find the count of submatrices
// with OR value 1
int matrixOrValueOne(bool arr[][n])
{
// Array to store prefix count of zeros from
// right to left for boolean array
int p_arr[n][n] = { 0 };
findPrefixCount(p_arr, arr);
// Variable to store the count of
// submatrices with OR value 0
int count_zero_submatrices = 0;
// Loop to evaluate each column of
// the prefix matrix uniquely.
// For each index of a column we will try to
// determine the number of sub-matrices
// starting from that index
// and has all 1s
for (int j = 0; j < n; j++) {
int i = n - 1;
// stack to store elements and the count
// of the numbers they popped
// First part of pair will be the
// value of inserted element.
// Second part will be the count
// of the number of elements pushed
// before with a greater value
stack > q;
// Variable to store the number of submatrices
// with all 0s
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 the final answer
return (n * (n + 1) * n * (n + 1)) / 4
- count_zero_submatrices;
}
// Driver Code
int main()
{
bool arr[][n] = { { 0, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 0 } };
cout << matrixOrValueOne(arr);
return 0;
}
Java
// Java program to count number of submatrices
// with OR value 1
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;
}
}
// Function to find required prefix-count
// for each row from right to left
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);
}
}
// Function to find the count of submatrices
// with OR value 1
static int matrixOrValueOne(boolean arr[][])
{
// Array to store prefix count of zeros from
// right to left for boolean array
int [][]p_arr = new int[n][n];
findPrefixCount(p_arr, arr);
// Variable to store the count of
// submatrices with OR value 0
int count_zero_submatrices = 0;
// Loop to evaluate each column of
// the prefix matrix uniquely.
// For each index of a column we will try to
// determine the number of sub-matrices
// starting from that index
// and has all 1s
for (int j = 0; j < n; j++)
{
int i = n - 1;
// stack to store elements and the count
// of the numbers they popped
// First part of pair will be the
// value of inserted element.
// Second part will be the count
// of the number of elements pushed
// before with a greater value
Stack q = new Stack();
// Variable to store the number of submatrices
// with all 0s
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 the final answer
return (n * (n + 1) * n * (n + 1)) / 4
- count_zero_submatrices;
}
// Driver Code
public static void main(String[] args)
{
boolean arr[][] = { { false, false, false },
{ false, true, false },
{ false, false, false } };
System.out.println(matrixOrValueOne(arr));
}
}
// This code is contributed by PrinciRaj1992
Python3
# Python3 program to count number
# of submatrices with OR value 1
# Function to find required prefix-count
# for each row from right to left
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])
# Function to find the count
# of submatrices with OR value 1
def matrixOrValueOne(arr):
# Array to store prefix count of zeros
# from right to left for boolean array
p_arr = [[0 for i in range(n)]
for j in range(n)]
findPrefixCount(p_arr, arr)
# Variable to store the count of
# submatrices with OR value 0
count_zero_submatrices = 0
# Loop to evaluate each column of
# the prefix matrix uniquely.
# For each index of a column we will try
# to determine the number of sub-matrices
# starting from that index and has all 1s
for j in range(0, n):
i = n - 1
# stack to store elements and the
# count of the numbers they popped
# First part of pair will be the
# value of inserted element.
# Second part will be the count
# of the number of elements pushed
# before with a greater value
q = []
# Variable to store the number
# of submatrices with all 0s
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 the final answer
return ((n * (n + 1) * n * (n + 1)) //
4 - count_zero_submatrices)
# Driver Code
if __name__ == "__main__":
n = 3
arr = [[0, 0, 0],
[0, 1, 0],
[0, 0, 0]]
print(matrixOrValueOne(arr))
# This code is contributed by Rituraj Jain
C#
// C# program to count number of submatrices
// with OR value 1
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;
}
}
// Function to find required prefix-count
// for each row from right to left
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);
}
}
// Function to find the count of submatrices
// with OR value 1
static int matrixOrValueOne(bool [,]arr)
{
// Array to store prefix count of zeros from
// right to left for bool array
int [,]p_arr = new int[n, n];
findPrefixCount(p_arr, arr);
// Variable to store the count of
// submatrices with OR value 0
int count_zero_submatrices = 0;
// Loop to evaluate each column of
// the prefix matrix uniquely.
// For each index of a column we will try to
// determine the number of sub-matrices
// starting from that index
// and has all 1s
for (int j = 0; j < n; j++)
{
int i = n - 1;
// stack to store elements and the count
// of the numbers they.Popped
// First part of pair will be the
// value of inserted element.
// Second part will be the count
// of the number of elements.Pushed
// before with a greater value
Stack q = new Stack();
// Variable to store the number of
// submatrices with all 0s
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 the final answer
return (n * (n + 1) * n * (n + 1)) / 4 -
count_zero_submatrices;
}
// Driver Code
public static void Main(String[] args)
{
bool [,]arr = { { false, false, false },
{ false, true, false },
{ false, false, false } };
Console.WriteLine(matrixOrValueOne(arr));
}
}
// This code is contributed by Rajput-Ji
输出:
16
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。