给定大小为N x M的矩阵mat[][]和大小为Q的数组查询 [] ,包含(a, b)对。任务是在矩阵mat[][] 的所有(axb)子矩阵中找到最大和。
Note: The rows and columns of the sub-matrix must be contiguous.
例子:
Input: N = 3, M = 4, Q = 1, queries[] = {(3, 2)}
mat[][] = {{1, 2, 3, 9},
{4, 5, 6, 2},
{8, 3, 2, 6}}
Output: 28
Explanation:
Here a = 3 and b = 2
The first 3×2 submatrix is:
1 2
4 5
8 3
The sum of elements in this is 23.
The second 3×2 submatrix is:
2 3
5 6
3 2
The sum of elements in this is 21.
The third 3×2 submatrix is:
3 9
6 2
2 6
The sum of elements in this is 28.
The maximum among these are 28.
Input: N = 3, M = 4, Q = 3, queries[] = {(1, 1), (2, 2), (3, 3)}
mat[][] = {{1, 2, 3, 9},
{4, 5, 6, 2},
{8, 3, 2, 6}}
Output: 9 20 38
朴素的方法:解决这个问题的最简单的方法是对每个查询,找到每个子矩阵的总和并打印最大的一个。
时间复杂度: O(Q*(N*M)^2),其中Q是查询次数, N和M是矩阵mat[][]的行数和列数。
辅助空间: O(1)
高效的方法:这个问题可以通过在回答所有查询之前做一些预处理来解决。请按照以下步骤解决此问题:
- 声明一个二维数组dp ,其中dp[i][j]存储从(0, 0)到(i, j)的元素总和。
- 对输入mat[][]进行一些预处理。声明一个函数,例如preProcess(mat, dp, n, m),执行以下步骤:
- 使用变量i在范围[0, m-1] 中迭代,并且 将dp[0][i]更新为mat[0][i]。
- 使用变量i在范围[1, n-1] 中迭代:
- 使用变量j在范围[0, m-1] 中迭代:
- 将dp[i][j]更新为dp[i-1][j] + mat[i][j]。
- 使用变量j在范围[0, m-1] 中迭代:
- 使用变量i在范围[0, n-1] 中迭代:
- 使用变量j在范围[1, m-1] 中迭代:
- 将dp[i][j]更新为dp[i][j] + dp[i][j-1]。
- 使用变量j在范围[1, m-1] 中迭代:
- 声明一个数组maxSum来存储每个查询的答案。
- 声明一个函数, sumQuery(dp, tli, tlj, rbi, rbj),其中tli和tlj分别是查询子矩阵左上角的行号和列号, rbi和rbj是右下角的行号和列号查询子矩阵,在O(1)时间内计算子矩阵的总和。
- 将变量res初始化为dp[rbi][rbj]以存储子矩阵的总和。
- 如果tl i 大于0 ,则删除(0, 0)和(tli-1, rbj)之间的元素。
- 如果tlj大于0,则删除 (0, 0) 和 (rbi, tlj-1) 之间的元素。
- 如果tli大于0且tlj大于0,则添加dp[tli-1][tlj-1]作为(0, 0)和(tli-1, tlj-1) 之间的元素减去两次。
- 使用变量qi在范围[0, q-1] 中迭代:
- 使用变量i在范围[0, n-queries[qi][0]] 中迭代:
- 使用变量j在范围[0, m-queries[qi][1]] 中迭代:
- 将maxSum[qi]更新为maxSum[qi]和sumQuery(dp, i, j, i + queries[qi][0] – 1, j + queries[qi][1] – 1)) 的最大值。
- 使用变量j在范围[0, m-queries[qi][1]] 中迭代:
- 使用变量i在范围[0, n-queries[qi][0]] 中迭代:
- 完成上述步骤后,打印数组maxSum作为每个查询的答案。
参考: https : //www.geeksforgeeks.org/submatrix-sum-queries/
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to preprcess input mat[N][M].
// This function mainly fills dp[N][M]
// such that dp[i][j] stores sum
// of elements from (0, 0) to (i, j)
void preProcess(vector> &mat,
vector> &dp,
int n, int m)
{
// Copy first row of mat[][] to dp[][]
for(int i = 0; i < m; i++)
{
dp[0][i] = mat[0][i];
}
// Do column wise sum
for(int i = 1; i < n; i++)
{
for(int j = 0; j < m; j++)
{
dp[i][j] = dp[i - 1][j] + mat[i][j];
}
}
// Do row wise sum
for(int i = 0; i < n; i++)
{
for(int j = 1; j < m; j++)
{
dp[i][j] += dp[i][j - 1];
}
}
}
// A O(1) time function to compute sum of submatrix
// between (tli, tlj) and (rbi, rbj) using dp[][]
// which is built by the preprocess function
int sumQuery(vector> dp, int tli,
int tlj, int rbi, int rbj)
{
// Result is now sum of elements
// between (0, 0) and (rbi, rbj)
int res = dp[rbi][rbj];
// Remove elements between (0, 0)
// and (tli-1, rbj)
if (tli > 0)
res = res - dp[tli - 1][rbj];
// Remove elements between (0, 0)
// and (rbi, tlj-1)
if (tlj > 0)
res = res - dp[rbi][tlj - 1];
// Add dp[tli-1][tlj-1] as elements
// between (0, 0) and (tli-1, tlj-1)
// are subtracted twice
if (tli > 0 && tlj > 0)
res = res + dp[tli - 1][tlj - 1];
return res;
}
// Function to find the maximum sum
// among all (a x b) sub-matrices of the matrix
vector maxSubMatrixSumQueries(vector> mat,
int n, int m,
vector> queries,
int q)
{
vector > dp(n, vector(m));
// Function call
preProcess(mat, dp, n, m);
vector maxSum((int)queries.size());
// Run a loop for finding
// answer for all queries
for(int qi = 0; qi < q; qi++)
{
for(int i = 0; i < n - queries[qi][0] + 1; i++)
{
for(int j = 0; j < m - queries[qi][1] + 1; j++)
{
maxSum[qi] = max(maxSum[qi],
sumQuery(dp, i, j,
i + queries[qi][0] - 1,
j + queries[qi][1] - 1));
}
}
}
return maxSum;
}
// Driver Code
int main()
{
// Given input
int n = 3, m = 4;
vector > mat = { { 1, 2, 3, 9 },
{ 4, 5, 6, 2 },
{ 8, 3, 2, 6 } };
int Q = 3;
vector >Queries = { { 1, 1 },
{ 2, 2 },
{ 3, 3 } };
// Function call
vector maxSum = maxSubMatrixSumQueries(
mat, n, m, Queries, Q);
// Print answer for all queries
for(int i = 0; i < Q; i++)
{
cout << maxSum[i] << " ";
}
}
// This code is contributed by mohit kumar 29
Java
// Java program for the above approach
public class Solution {
// Function to preprcess input mat[N][M].
// This function mainly fills dp[N][M]
// such that dp[i][j] stores sum
// of elements from (0, 0) to (i, j)
static void preProcess(int mat[][], int dp[][],
int n, int m)
{
// Copy first row of mat[][] to dp[][]
for (int i = 0; i < m; i++) {
dp[0][i] = mat[0][i];
}
// Do column wise sum
for (int i = 1; i < n; i++) {
for (int j = 0; j < m; j++) {
dp[i][j] = dp[i - 1][j] + mat[i][j];
}
}
// Do row wise sum
for (int i = 0; i < n; i++) {
for (int j = 1; j < m; j++) {
dp[i][j] += dp[i][j - 1];
}
}
}
// A O(1) time function to compute sum of submatrix
// between (tli, tlj) and (rbi, rbj) using dp[][]
// which is built by the preprocess function
static int sumQuery(int dp[][], int tli,
int tlj, int rbi,
int rbj)
{
// Result is now sum of elements
// between (0, 0) and (rbi, rbj)
int res = dp[rbi][rbj];
// Remove elements between (0, 0)
// and (tli-1, rbj)
if (tli > 0)
res = res - dp[tli - 1][rbj];
// Remove elements between (0, 0)
// and (rbi, tlj-1)
if (tlj > 0)
res = res - dp[rbi][tlj - 1];
// Add dp[tli-1][tlj-1] as elements
// between (0, 0) and (tli-1, tlj-1)
// are subtracted twice
if (tli > 0 && tlj > 0)
res
= res + dp[tli - 1][tlj - 1];
return res;
}
// Function to find the maximum sum
// among all (a x b) sub-matrices of the matrix
static int[] maxSubMatrixSumQueries(
int[][] mat,
int n, int m,
int[][] queries,
int q)
{
int dp[][] = new int[n][m];
// Function call
preProcess(mat, dp, n, m);
int maxSum[] = new int[queries.length];
// Run a loop for finding
// answer for all queries
for (int qi = 0; qi < q; qi++) {
for (int i = 0; i < n - queries[qi][0] + 1; i++) {
for (int j = 0; j < m - queries[qi][1] + 1; j++) {
maxSum[qi]
= Math.max(maxSum[qi],
sumQuery(dp, i, j,
i + queries[qi][0] - 1,
j + queries[qi][1] - 1));
}
}
}
return maxSum;
}
// Driver Code
public static void main(String args[])
{
// Given input
int n = 3, m = 4;
int mat[][] = { { 1, 2, 3, 9 },
{ 4, 5, 6, 2 },
{ 8, 3, 2, 6 } };
int Q = 3;
int Queries[][] = { { 1, 1 },
{ 2, 2 },
{ 3, 3 } };
// Function call
int maxSum[]
= maxSubMatrixSumQueries(
mat, n, m, Queries, Q);
// Print answer for all queries
for (int i = 0; i < Q; i++) {
System.out.print(maxSum[i] + " ");
}
}
}
C#
using System;
public class GFG{
// Function to preprcess input mat[N][M].
// This function mainly fills dp[N][M]
// such that dp[i][j] stores sum
// of elements from (0, 0) to (i, j)
static void preProcess(int[,] mat, int[,] dp,
int n, int m)
{
// Copy first row of mat[][] to dp[][]
for (int i = 0; i < m; i++) {
dp[0,i] = mat[0,i];
}
// Do column wise sum
for (int i = 1; i < n; i++) {
for (int j = 0; j < m; j++) {
dp[i,j] = dp[i - 1,j] + mat[i,j];
}
}
// Do row wise sum
for (int i = 0; i < n; i++) {
for (int j = 1; j < m; j++) {
dp[i,j] += dp[i,j - 1];
}
}
}
// A O(1) time function to compute sum of submatrix
// between (tli, tlj) and (rbi, rbj) using dp[][]
// which is built by the preprocess function
static int sumQuery(int[,] dp, int tli,
int tlj, int rbi,
int rbj)
{
// Result is now sum of elements
// between (0, 0) and (rbi, rbj)
int res = dp[rbi,rbj];
// Remove elements between (0, 0)
// and (tli-1, rbj)
if (tli > 0)
res = res - dp[tli - 1,rbj];
// Remove elements between (0, 0)
// and (rbi, tlj-1)
if (tlj > 0)
res = res - dp[rbi,tlj - 1];
// Add dp[tli-1][tlj-1] as elements
// between (0, 0) and (tli-1, tlj-1)
// are subtracted twice
if (tli > 0 && tlj > 0)
res
= res + dp[tli - 1,tlj - 1];
return res;
}
// Function to find the maximum sum
// among all (a x b) sub-matrices of the matrix
static int[] maxSubMatrixSumQueries(
int[,] mat,
int n, int m,
int[,] queries,
int q)
{
int[,] dp = new int[n,m];
// Function call
preProcess(mat, dp, n, m);
int[] maxSum = new int[queries.GetLength(0)];
// Run a loop for finding
// answer for all queries
for (int qi = 0; qi < q; qi++) {
for (int i = 0; i < n - queries[qi,0] + 1; i++) {
for (int j = 0; j < m - queries[qi,1] + 1; j++) {
maxSum[qi]
= Math.Max(maxSum[qi],
sumQuery(dp, i, j,
i + queries[qi,0] - 1,
j + queries[qi,1] - 1));
}
}
}
return maxSum;
}
// Driver Code
static public void Main (){
// Given input
int n = 3, m = 4;
int[,] mat = { { 1, 2, 3, 9 },
{ 4, 5, 6, 2 },
{ 8, 3, 2, 6 } };
int Q = 3;
int[,] Queries = { { 1, 1 },
{ 2, 2 },
{ 3, 3 } };
// Function call
int[] maxSum
= maxSubMatrixSumQueries(
mat, n, m, Queries, Q);
// Print answer for all queries
for (int i = 0; i < Q; i++) {
Console.Write(maxSum[i] + " ");
}
}
}
// This code is contributed by patel2127.
Javascript
9 20 38
时间复杂度: O(Q*N*M),其中Q是查询次数,N和M是矩阵mat[][]的行数和列数。
辅助空间: O(N*M)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。