给定一个大小为M * N的二进制矩阵mat[][]和形式为{pi, pj, qi, qj} 的Q查询,每个查询的任务是计算单元格子矩阵中0的数量( pi, pj)到(qi, qj) 。
例子:
Input: mat[][] = {{0, 1, 0, 1, 1, 1, 0}, {1, 0, 1, 1, 1, 0, 1}, {1, 1, 0, 0, 1, 1, 0}, {1, 1, 1, 1, 1, 0, 1}, {0, 0, 1, 0, 1, 1, 1}, {1, 1, 0, 1, 1, 0, 1 }}, Q[] = {{0, 1, 3, 2}, {2, 2, 4, 5}, {4, 3, 5, 6}}
Output: 3 4 2
Explanation:
The submatrix from indices (0, 1) to (3, 2) contains 3 0s.
The submatrix from indices (2, 2) to (4, 5) contains 4 0s.
The submatrix from indices (4, 3) to (5, 6) contains 2 0s.
Input: mat[][] = {{0, 1, 0}, {1, 0, 1}}, Q[] = {{0, 0, 2, 2}}
Output: 3
朴素的方法:解决问题的最简单方法是通过迭代子矩阵来计算每个查询的0数,并打印每个查询的计数。
时间复杂度: O(M*N*Q)
辅助空间: O(1)
高效的方法:为了优化上述方法,其思想是对给定的矩阵mat[][]进行预处理。创建一个计数矩阵,比如prefixCnt[M][N] ,这样prefix_cnt[i][j]存储索引(0, 0)到(i, j)内的子矩阵中0的计数。按照以下步骤计算prefixCnt[][] :
- 如果mat[i][j]为0 ,则用1初始化prefixCnt[i][j] 。否则,用0初始化。
- 找到每行和每列的前缀总和并相应地更新矩阵。
一次,计算矩阵prefixCnt[][]可以在O(1) 时间内评估任何子矩阵中0的计数。下面是计算从(pi, pj)到(qi, qj) 的每个子矩阵中的0的表达式,可以通过以下方式计算:
cnt = prefixCnt[qi][qj] – prefixCnt[pi-1][qj] – prefixCnt[qi][pj – 1] + prefixCnt[pi – 1][pj – 1]
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
#define M 6
#define N 7
// Function to compute the matrix
// prefixCnt[M][N] from mat[M][N] such
// that prefixCnt[i][j] stores the
// count of 0's from (0, 0) to (i, j)
void preCompute(int mat[M][N],
int prefixCnt[M][N])
{
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
// Initialize prefixCnt[i][j]
// with 1 if mat[i][j] is 0
if (mat[i][j] == 0) {
prefixCnt[i][j] = 1;
}
// Otherwise, assign with 0
else {
prefixCnt[i][j] = 0;
}
}
}
// Calculate prefix sum for each row
for (int i = 0; i < M; i++)
for (int j = 1; j < N; j++)
prefixCnt[i][j] += prefixCnt[i][j - 1];
// Calculate prefix sum for each column
for (int i = 1; i < M; i++)
for (int j = 0; j < N; j++)
prefixCnt[i][j] += prefixCnt[i - 1][j];
}
// Function to compute count of 0's
// in submatrix from (pi, pj) to
// (qi, qj) from prefixCnt[M][N]
int countQuery(int prefixCnt[M][N],
int pi, int pj,
int qi, int qj)
{
// Initialize that count of 0's
// in the sub-matrix within
// indices (0, 0) to (qi, qj)
int cnt = prefixCnt[qi][qj];
// Subtract count of 0's within
// indices (0, 0) and (pi-1, qj)
if (pi > 0)
cnt -= prefixCnt[pi - 1][qj];
// Subtract count of 0's within
// indices (0, 0) and (qi, pj-1)
if (pj > 0)
cnt -= prefixCnt[qi][pj - 1];
// Add prefixCnt[pi - 1][pj - 1]
// because its value has been added
// once but subtracted twice
if (pi > 0 && pj > 0)
cnt += prefixCnt[pi - 1][pj - 1];
return cnt;
}
// Function to count the 0s in the
// each given submatrix
void count0s(int mat[M][N], int Q[][4],
int sizeQ)
{
// Stores the prefix sum of each
// row and column
int prefixCnt[M][N];
// Compute matrix prefixCnt[][]
preCompute(mat, prefixCnt);
for (int i = 0; i < sizeQ; i++) {
// Function Call for each query
cout << countQuery(prefixCnt, Q[i][0],
Q[i][1], Q[i][2],
Q[i][3])
<< ' ';
}
}
// Driver Code
int main()
{
// Given matrix
int mat[M][N] = {
{ 0, 1, 0, 1, 1, 1, 0 },
{ 1, 0, 1, 1, 1, 0, 1 },
{ 1, 1, 0, 0, 1, 1, 0 },
{ 1, 1, 1, 1, 1, 0, 1 },
{ 0, 0, 1, 0, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1 }
};
int Q[][4] = { { 0, 1, 3, 2 },
{ 2, 2, 4, 5 },
{ 4, 3, 5, 6 } };
int sizeQ = sizeof(Q) / sizeof(Q[0]);
// Function Call
count0s(mat, Q, sizeQ);
return 0;
}
Java
// Java program for the above approach
class GFG{
final static int M = 6;
final static int N = 7;
// Function to compute the matrix
// prefixCnt[M][N] from mat[M][N] such
// that prefixCnt[i][j] stores the
// count of 0's from (0, 0) to (i, j)
static void preCompute(int mat[][], int prefixCnt[][])
{
for(int i = 0; i < M; i++)
{
for(int j = 0; j < N; j++)
{
// Initialize prefixCnt[i][j]
// with 1 if mat[i][j] is 0
if (mat[i][j] == 0)
{
prefixCnt[i][j] = 1;
}
// Otherwise, assign with 0
else
{
prefixCnt[i][j] = 0;
}
}
}
// Calculate prefix sum for each row
for(int i = 0; i < M; i++)
for(int j = 1; j < N; j++)
prefixCnt[i][j] += prefixCnt[i][j - 1];
// Calculate prefix sum for each column
for(int i = 1; i < M; i++)
for(int j = 0; j < N; j++)
prefixCnt[i][j] += prefixCnt[i - 1][j];
}
// Function to compute count of 0's
// in submatrix from (pi, pj) to
// (qi, qj) from prefixCnt[M][N]
static int countQuery(int prefixCnt[][],
int pi, int pj,
int qi, int qj)
{
// Initialize that count of 0's
// in the sub-matrix within
// indices (0, 0) to (qi, qj)
int cnt = prefixCnt[qi][qj];
// Subtract count of 0's within
// indices (0, 0) and (pi-1, qj)
if (pi > 0)
cnt -= prefixCnt[pi - 1][qj];
// Subtract count of 0's within
// indices (0, 0) and (qi, pj-1)
if (pj > 0)
cnt -= prefixCnt[qi][pj - 1];
// Add prefixCnt[pi - 1][pj - 1]
// because its value has been added;
// once but subtracted twice
if (pi > 0 && pj > 0)
cnt += prefixCnt[pi - 1][pj - 1];
return cnt;
}
// Function to count the 0s in the
// each given submatrix
static void count0s(int mat[][], int Q[][],
int sizeQ)
{
// Stores the prefix sum of each
// row and column
int prefixCnt[][] = new int[M][N];
// Compute matrix prefixCnt[][]
preCompute(mat, prefixCnt);
for(int i = 0; i < sizeQ; i++)
{
// Function Call for each query
System.out.print(countQuery(prefixCnt, Q[i][0],
Q[i][1],
Q[i][2],
Q[i][3]) + " ");
}
}
// Driver Code
public static void main (String[] args)
{
// Given matrix
int mat[][] = { { 0, 1, 0, 1, 1, 1, 0 },
{ 1, 0, 1, 1, 1, 0, 1 },
{ 1, 1, 0, 0, 1, 1, 0 },
{ 1, 1, 1, 1, 1, 0, 1 },
{ 0, 0, 1, 0, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1 } };
int Q[][] = { { 0, 1, 3, 2 },
{ 2, 2, 4, 5 },
{ 4, 3, 5, 6 } };
int sizeQ = Q.length;
// Function Call
count0s(mat, Q, sizeQ);
}
}
// This code is contributed by AnkThon
Python3
# Python3 program for the above approach
M = 6
N = 7
# Function to compute the matrix
# prefixCnt[M][N] from mat[M][N] such
# that prefixCnt[i][j] stores the
# count of 0's from (0, 0) to (i, j)
def preCompute(mat, prefixCnt):
for i in range(M):
for j in range(N):
# Initialize prefixCnt[i][j]
# with 1 if mat[i][j] is 0
if (mat[i][j] == 0):
prefixCnt[i][j] = 1
# Otherwise, assign with 0
else:
prefixCnt[i][j] = 0
# Calculate prefix sum for each row
for i in range(M):
for j in range(1, N):
prefixCnt[i][j] += prefixCnt[i][j - 1]
# Calculate prefix sum for each column
for i in range(1, M):
for j in range(N):
prefixCnt[i][j] += prefixCnt[i - 1][j]
return prefixCnt
# Function to compute count of 0's
# in submatrix from (pi, pj) to
# (qi, qj) from prefixCnt[M][N]
def countQuery(prefixCnt, pi, pj, qi, qj):
# Initialize that count of 0's
# in the sub-matrix within
# indices (0, 0) to (qi, qj)
cnt = prefixCnt[qi][qj]
# Subtract count of 0's within
# indices (0, 0) and (pi-1, qj)
if (pi > 0):
cnt -= prefixCnt[pi - 1][qj]
# Subtract count of 0's within
# indices (0, 0) and (qi, pj-1)
if (pj > 0):
cnt -= prefixCnt[qi][pj - 1]
# Add prefixCnt[pi - 1][pj - 1]
# because its value has been added
# once but subtracted twice
if (pi > 0 and pj > 0):
cnt += prefixCnt[pi - 1][pj - 1]
return cnt
# Function to count the 0s in the
# each given submatrix
def count0s(mat, Q, sizeQ):
# Stores the prefix sum of each
# row and column
prefixCnt = [[ 0 for i in range(N)] for i in range(M)]
# Compute matrix prefixCnt[][]
prefixCnt = preCompute(mat, prefixCnt)
for i in range(sizeQ):
# Function Call for each query
print(countQuery(prefixCnt, Q[i][0], Q[i][1], Q[i][2], Q[i][3]), end=" ")
# Driver Code
if __name__ == '__main__':
# Given matrix
mat = [[ 0, 1, 0, 1, 1, 1, 0 ],
[ 1, 0, 1, 1, 1, 0, 1 ],
[ 1, 1, 0, 0, 1, 1, 0 ],
[ 1, 1, 1, 1, 1, 0, 1 ],
[ 0, 0, 1, 0, 1, 1, 1 ],
[ 1, 1, 0, 1, 1, 0, 1 ] ]
Q= [ [ 0, 1, 3, 2 ],
[ 2, 2, 4, 5 ],
[ 4, 3, 5, 6 ] ]
sizeQ = len(Q)
# Function Call
count0s(mat, Q, sizeQ)
# This code is contributed by mohit kumar 29
C#
// C# program for the above approach
using System;
class GFG
{
static int M = 6;
static int N = 7;
// Function to compute the matrix
// prefixCnt[M][N] from mat[M][N] such
// that prefixCnt[i][j] stores the
// count of 0's from (0, 0) to (i, j)
static void preCompute(int [,]mat, int [,]prefixCnt)
{
for(int i = 0; i < M; i++)
{
for(int j = 0; j < N; j++)
{
// Initialize prefixCnt[i][j]
// with 1 if mat[i,j] is 0
if (mat[i, j] == 0)
{
prefixCnt[i, j] = 1;
}
// Otherwise, assign with 0
else
{
prefixCnt[i, j] = 0;
}
}
}
// Calculate prefix sum for each row
for(int i = 0; i < M; i++)
for(int j = 1; j < N; j++)
prefixCnt[i, j] += prefixCnt[i, j - 1];
// Calculate prefix sum for each column
for(int i = 1; i < M; i++)
for(int j = 0; j < N; j++)
prefixCnt[i, j] += prefixCnt[i - 1, j];
}
// Function to compute count of 0's
// in submatrix from (pi, pj) to
// (qi, qj) from prefixCnt[M][N]
static int countQuery(int [,]prefixCnt,
int pi, int pj,
int qi, int qj)
{
// Initialize that count of 0's
// in the sub-matrix within
// indices (0, 0) to (qi, qj)
int cnt = prefixCnt[qi, qj];
// Subtract count of 0's within
// indices (0, 0) and (pi-1, qj)
if (pi > 0)
cnt -= prefixCnt[pi - 1, qj];
// Subtract count of 0's within
// indices (0, 0) and (qi, pj-1)
if (pj > 0)
cnt -= prefixCnt[qi, pj - 1];
// Add prefixCnt[pi - 1][pj - 1]
// because its value has been added;
// once but subtracted twice
if (pi > 0 && pj > 0)
cnt += prefixCnt[pi - 1, pj - 1];
return cnt;
}
// Function to count the 0s in the
// each given submatrix
static void count0s(int [,]mat, int [,]Q,
int sizeQ)
{
// Stores the prefix sum of each
// row and column
int [,]prefixCnt = new int[M, N];
// Compute matrix prefixCnt[,]
preCompute(mat, prefixCnt);
for(int i = 0; i < sizeQ; i++)
{
// Function Call for each query
Console.Write(countQuery(prefixCnt, Q[i, 0],
Q[i, 1],
Q[i, 2],
Q[i, 3]) + " ");
}
}
// Driver Code
public static void Main(string[] args)
{
// Given matrix
int [,]mat = { { 0, 1, 0, 1, 1, 1, 0 },
{ 1, 0, 1, 1, 1, 0, 1 },
{ 1, 1, 0, 0, 1, 1, 0 },
{ 1, 1, 1, 1, 1, 0, 1 },
{ 0, 0, 1, 0, 1, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1 } };
int [,]Q = { { 0, 1, 3, 2 },
{ 2, 2, 4, 5 },
{ 4, 3, 5, 6 } };
int sizeQ = Q.GetLength(0);
// Function Call
count0s(mat, Q, sizeQ);
}
}
// This code is contributed by AnkThon
Javascript
3 4 2
时间复杂度: O(M*N + Q)
辅助空间: O(M*N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live