Given a 2d array mat[][] of order n * n, and an integer k. Your task is to find a submatrix of order k * k, such that sum of all the elements in the submatrix is maximum possible.
Note: Matrix mat[][] contains zero, positive and negative integers.
Examples:
Input: k = 3
mat[][] = [ [ 1, 2, -1, 4 ]
[ -8, -3, 4, 2 ]
[ 3, 8, 10, -8 ]
[ -4, -1, 1, 7 ] ]
Output: 20
Explanation: The submatrix enclosed in blue boundary is the maximum sum submatrix of order 3 * 3.Input: k = 3
mat[][] = [ [ 1, 1, 1, 1, 1 ]
[ 2, 2, 2, 2, 2 ]
[ 3, 8, 6, 7, 3 ]
[ 4, 4, 4, 4, 4 ]
[ 5, 5, 5, 5, 5 ] ]
Output: 48
Explanation: The following submatrix of order k * k has sum 48, which is maximum possible:
[ [ 8, 6, 7 ]
[ 4, 4, 4 ]
[ 5, 5, 5 ] ]Input: k = 1
mat[][] = [ [ 4 ] ]
Output: 4
Explanation: The given matrix contains only a single element, thus the max possible sum is 4.
This problem is mainly an extension of Maximum Sum of a Subarray of Size k
[Naive Approach] - Generating All Submatrices - O(n ^ 2 * k ^ 2) Time and O(1) Space
The idea is to generate all possible submatrices of order k * k, and find sum of its elements. The maximum obtained sum is the answer.
We run two nested loops, where the outer loop runs from 0 to n - k, and marks the row, while the inner row runs from 0 to n - k and marks the current column. For each iteration of the inner loop, again run two nested loops, where the outer loop runs from i to i + k - 1, and inner loop runs from j to j + k - 1. For each iteration of innermost loop add the cell value to the sum. At last store the max of obtained sum and current answer.
#include <bits/stdc++.h>
using namespace std;
// Function to find the submatrix of
// order k * k with maximum sum of elements
int maximumSum(vector<vector<int>> &mat, int k) {
int n = mat.size();
// to store the answer
int ans = INT_MIN;
// generate all possible submatrix
// of order k * k
for(int i = 0; i <= n - k; i++) {
for(int j = 0; j <= n - k; j++) {
// compute sum of submatrix
// of order k * k
int sum = 0;
for(int p = i; p < i + k; p++) {
for(int q = j; q < j + k; q++) {
sum += mat[p][q];
}
}
// update the maximum sum
ans = max(ans, sum);
}
}
return ans;
}
int main() {
vector<vector<int>> mat = {
{ 1, 2, -1, 4 },
{ -8, -3, 4, 2 },
{ 3, 8, 10, -8 },
{ -4, -1, 1, 7 } };
int k = 3;
cout << maximumSum(mat, k);
return 0;
}
// Function to find the submatrix of
// order k * k with maximum sum of elements
import java.util.*;
class GfG {
// Function to find the submatrix of
// order k * k with maximum sum of elements
static int maximumSum(int[][] mat, int k) {
int n = mat.length;
// to store the answer
int ans = Integer.MIN_VALUE;
// generate all possible submatrix
// of order k * k
for (int i = 0; i <= n - k; i++) {
for (int j = 0; j <= n - k; j++) {
// compute sum of submatrix
// of order k * k
int sum = 0;
for (int p = i; p < i + k; p++) {
for (int q = j; q < j + k; q++) {
sum += mat[p][q];
}
}
// update the maximum sum
ans = Math.max(ans, sum);
}
}
return ans;
}
public static void main(String[] args) {
int[][] mat = {
{ 1, 2, -1, 4 },
{ -8, -3, 4, 2 },
{ 3, 8, 10, -8 },
{ -4, -1, 1, 7 }
};
int k = 3;
System.out.println(maximumSum(mat, k));
}
}
# Function to find the submatrix of
# order k * k with maximum sum of elements.
def maximumSum(mat, k):
n = len(mat)
# to store the answer
ans = -float('inf')
# generate all possible submatrix
# of order k * k
for i in range(0, len(mat) - k + 1):
for j in range(0, len(mat) - k + 1):
# compute sum of submatrix
# of order k * k
sum_val = 0
for p in range(i, i + k):
for q in range(j, j + k):
sum_val += mat[p][q]
# update the maximum sum
ans = max(ans, sum_val)
return ans
if __name__ == "__main__":
mat = [
[ 1, 2, -1, 4 ],
[ -8, -3, 4, 2 ],
[ 3, 8, 10, -8 ],
[ -4, -1, 1, 7 ]
]
k = 3
print(maximumSum(mat, k))
// Function to find the submatrix of
// order k * k with maximum sum of elements
using System;
using System.Collections.Generic;
class GfG {
// Function to find the submatrix of
// order k * k with maximum sum of elements
static int maximumSum(List<List<int>> mat, int k) {
int n = mat.Count;
// to store the answer
int ans = int.MinValue;
// generate all possible submatrix
// of order k * k
for (int i = 0; i <= n - k; i++) {
for (int j = 0; j <= n - k; j++) {
// compute sum of submatrix
// of order k * k
int sum = 0;
for (int p = i; p < i + k; p++) {
for (int q = j; q < j + k; q++) {
sum += mat[p][q];
}
}
// update the maximum sum
ans = Math.Max(ans, sum);
}
}
return ans;
}
static void Main() {
List<List<int>> mat = new List<List<int>> {
new List<int> { 1, 2, -1, 4 },
new List<int> { -8, -3, 4, 2 },
new List<int> { 3, 8, 10, -8 },
new List<int> { -4, -1, 1, 7 }
};
int k = 3;
Console.WriteLine(maximumSum(mat, k));
}
}
// Function to find the submatrix of
// order k * k with maximum sum of elements.
function maximumSum(mat, k) {
let n = mat.length;
// to store the answer
let ans = -Infinity;
// generate all possible submatrix
// of order k * k
for (let i = 0; i <= n - k; i++) {
for (let j = 0; j <= n - k; j++) {
// compute sum of submatrix
// of order k * k
let sum = 0;
for (let p = i; p < i + k; p++) {
for (let q = j; q < j + k; q++) {
sum += mat[p][q];
}
}
// update the maximum sum
ans = Math.max(ans, sum);
}
}
return ans;
}
let mat = [
[ 1, 2, -1, 4 ],
[ -8, -3, 4, 2 ],
[ 3, 8, 10, -8 ],
[ -4, -1, 1, 7 ]
];
let k = 3;
console.log(maximumSum(mat, k));
Output
20
[Expected Approach] - By Calculating Strips Sum - O(n ^ 2) Time and O(n ^ 2) Space
The idea is to preprocess the given square matrix. In the pre-processing step, calculate sum of all vertical strips of size k x 1 in a temporary square matrix stripSum[][]. Once we have sum of all vertical strips, we can calculate sum of first sub-square in a row as sum of first k strips in that row, and for remaining sub-squares, we can calculate sum in constant time by removing the leftmost strip of previous sub-square and adding the rightmost strip of new square.
#include <bits/stdc++.h>
using namespace std;
// Function to find the submatrix of
// order k * k with maximum sum of elements
int maximumSum(vector<vector<int>> &mat, int k) {
int n = mat.size();
// create 2d array to store strips sum
vector<vector<int>> stripSum(n, vector<int>(n, 0));
// calculate the sum column by column
for(int j = 0; j < n; j++) {
int sum = 0;
// calculate sum of first k * 1 strip
for(int i = 0; i < k; i++) {
sum += mat[i][j];
}
stripSum[0][j] = sum;
// calculate sum of remaining strips
for(int i = 1; i <= n - k; i++) {
sum += mat[i + k - 1][j] - mat[i - 1][j];
stripSum[i][j] = sum;
}
}
// to store the answer
int ans = INT_MIN;
// calculate the sum of k * k
// submatrix using the sum of strips
for(int i = 0; i <= n - k; i++) {
int sum = 0;
// calculate sum of first k strips
for(int j = 0; j < k; j++) {
sum += stripSum[i][j];
}
// update the maximum sum
ans = max(ans, sum);
// calculate sum of remaining strips
for(int j = 1; j <= n - k; j++) {
sum += stripSum[i][j + k - 1] - stripSum[i][j - 1];
ans = max(ans, sum);
}
}
return ans;
}
int main() {
vector<vector<int>> mat = {
{ 1, 2, -1, 4 },
{ -8, -3, 4, 2 },
{ 3, 8, 10, -8 },
{ -4, -1, 1, 7 } };
int k = 3;
cout << maximumSum(mat, k);
return 0;
}
// Function to find the submatrix of
// order k * k with maximum sum of elements
import java.util.*;
class GfG {
// Function to find the submatrix of
// order k * k with maximum sum of elements
static int maximumSum(int[][] mat, int k) {
int n = mat.length;
// create 2d array to store strips sum
int[][] stripSum = new int[n][n];
// calculate the sum column by column
for (int j = 0; j < n; j++) {
int sum = 0;
// calculate sum of first k * 1 strip
for (int i = 0; i < k; i++) {
sum += mat[i][j];
}
stripSum[0][j] = sum;
// calculate sum of remaining strips
for (int i = 1; i <= n - k; i++) {
sum += mat[i + k - 1][j] - mat[i - 1][j];
stripSum[i][j] = sum;
}
}
// to store the answer
int ans = Integer.MIN_VALUE;
// calculate the sum of k * k
// submatrix using the sum of strips
for (int i = 0; i <= n - k; i++) {
int sum = 0;
// calculate sum of first k strips
for (int j = 0; j < k; j++) {
sum += stripSum[i][j];
}
// update the maximum sum
ans = Math.max(ans, sum);
// calculate sum of remaining strips
for (int j = 1; j <= n - k; j++) {
sum += stripSum[i][j + k - 1] - stripSum[i][j - 1];
ans = Math.max(ans, sum);
}
}
return ans;
}
public static void main(String[] args) {
int[][] mat = {
{ 1, 2, -1, 4 },
{ -8, -3, 4, 2 },
{ 3, 8, 10, -8 },
{ -4, -1, 1, 7 }
};
int k = 3;
System.out.println(maximumSum(mat, k));
}
}
# Function to find the submatrix of
# order k * k with maximum sum of elements.
def maximumSum(mat, k):
n = len(mat)
# create 2d array to store strips sum
stripSum = [[0 for _ in range(n)] for _ in range(n)]
# calculate the sum column by column
for j in range(n):
sum_val = 0
# calculate sum of first k * 1 strip
for i in range(k):
sum_val += mat[i][j]
stripSum[0][j] = sum_val
# calculate sum of remaining strips
for i in range(1, n - k + 1):
sum_val += mat[i + k - 1][j] - mat[i - 1][j]
stripSum[i][j] = sum_val
# to store the answer
ans = -float('inf')
# calculate the sum of k * k
# submatrix using the sum of strips
for i in range(0, n - k + 1):
sum_val = 0
# calculate sum of first k strips
for j in range(k):
sum_val += stripSum[i][j]
ans = max(ans, sum_val)
# calculate sum of remaining strips
for j in range(1, n - k + 1):
sum_val += stripSum[i][j + k - 1] - stripSum[i][j - 1]
ans = max(ans, sum_val)
return ans
if __name__ == "__main__":
mat = [
[ 1, 2, -1, 4 ],
[ -8, -3, 4, 2 ],
[ 3, 8, 10, -8 ],
[ -4, -1, 1, 7 ]
]
k = 3
print(maximumSum(mat, k))
// Function to find the submatrix of
// order k * k with maximum sum of elements
using System;
using System.Collections.Generic;
class GfG {
// Function to find the submatrix of
// order k * k with maximum sum of elements
static int maximumSum(List<List<int>> mat, int k) {
int n = mat.Count;
// create 2d array to store strips sum
List<List<int>> stripSum = new List<List<int>>();
for (int i = 0; i < n; i++) {
List<int> row = new List<int>();
for (int j = 0; j < n; j++) {
row.Add(0);
}
stripSum.Add(row);
}
// calculate the sum column by column
for (int j = 0; j < n; j++) {
int sum = 0;
// calculate sum of first k * 1 strip
for (int i = 0; i < k; i++) {
sum += mat[i][j];
}
stripSum[0][j] = sum;
// calculate sum of remaining strips
for (int i = 1; i <= n - k; i++) {
sum += mat[i + k - 1][j] - mat[i - 1][j];
stripSum[i][j] = sum;
}
}
// to store the answer
int ans = int.MinValue;
// calculate the sum of k * k
// submatrix using the sum of strips
for (int i = 0; i <= n - k; i++) {
int sum = 0;
// calculate sum of first k strips
for (int j = 0; j < k; j++) {
sum += stripSum[i][j];
}
ans = Math.Max(ans, sum);
// calculate sum of remaining strips
for (int j = 1; j <= n - k; j++) {
sum += stripSum[i][j + k - 1] - stripSum[i][j - 1];
ans = Math.Max(ans, sum);
}
}
return ans;
}
static void Main() {
List<List<int>> mat = new List<List<int>> {
new List<int> { 1, 2, -1, 4 },
new List<int> { -8, -3, 4, 2 },
new List<int> { 3, 8, 10, -8 },
new List<int> { -4, -1, 1, 7 }
};
int k = 3;
Console.WriteLine(maximumSum(mat, k));
}
}
// Function to find the submatrix of
// order k * k with maximum sum of elements.
function maximumSum(mat, k) {
let n = mat.length;
// create 2d array to store strips sum
let stripSum = new Array(n);
for (let i = 0; i < n; i++) {
stripSum[i] = new Array(n).fill(0);
}
// calculate the sum column by column
for (let j = 0; j < n; j++) {
let sum = 0;
// calculate sum of first k * 1 strip
for (let i = 0; i < k; i++) {
sum += mat[i][j];
}
stripSum[0][j] = sum;
// calculate sum of remaining strips
for (let i = 1; i <= n - k; i++) {
sum += mat[i + k - 1][j] - mat[i - 1][j];
stripSum[i][j] = sum;
}
}
// to store the answer
let ans = -Infinity;
// calculate the sum of k * k
// submatrix using the sum of strips
for (let i = 0; i <= n - k; i++) {
let sum = 0;
// calculate sum of first k strips
for (let j = 0; j < k; j++) {
sum += stripSum[i][j];
}
ans = Math.max(ans, sum);
// calculate sum of remaining strips
for (let j = 1; j <= n - k; j++) {
sum += stripSum[i][j + k - 1] - stripSum[i][j - 1];
ans = Math.max(ans, sum);
}
}
return ans;
}
let mat = [
[ 1, 2, -1, 4 ],
[ -8, -3, 4, 2 ],
[ 3, 8, 10, -8 ],
[ -4, -1, 1, 7 ]
];
let k = 3;
console.log(maximumSum(mat, k));
Output
20
[Alternate Approach] - Using Dynamic Programming - O(n ^ 2) Time and O(n ^ 2) Space
The idea is to use Dynamic Programming to precompute the sum of all the sub-matrices having their top-left cell [0, 0] (Like prefix sum in 1 D array), and then use it to find the sums of submatrices of order k * k and pick the maximum possible. To do so, create a 2d array dp[][] of order n * n, where dp[i][j] stores the sum of all the elements of sub-matrix mat[0...i][0...j].
Follow the below given steps:
- Create a 2d array dp[][] of order n * n to store the sum of elements of all the submatrices
- To calculate the sum of elements of submatrix mat[0...i][0...j], i.e., dp[i][j], add dp[i-1][j], dp[i][j-1], and mat[i][j], and subtract dp[i-1][j-1], as this submatrix will get added twice while adding two other sub-matrices.
- Now, to calculate the sum of elements of sub-matrix having its right-bottom cell [i, j], subtract dp[i-k][j] and dp[i][j - k] from dp[i][j], and add dp[i - k][j - k], as this overlapping sub-matrix will get deleted twice.
- Do the same for all the cells of the matrix, and store the maximum value as the answer.
#include <bits/stdc++.h>
using namespace std;
// Function to find the submatrix of
// order k * k with maximum sum of elements
int maximumSum(vector<vector<int>> &mat, int k) {
int n = mat.size();
// create a 2d array to store sum
// elements of submatrices
vector<vector<int>> dp(n, vector<int>(n, 0));
// calculate the sum of submatrices
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
// add the current element
dp[i][j] = mat[i][j];
// add the submatrix ending at left
if(j > 0) {
dp[i][j] += dp[i][j - 1];
}
// add the submatrix ending at top
if(i > 0) {
dp[i][j] += dp[i - 1][j];
}
// remove the overlapping submatrix
if(i > 0 && j > 0) {
dp[i][j] -= dp[i - 1][j - 1];
}
}
}
// to store the answer
int ans = INT_MIN;
// generate all possible submatrices
// of order k * k
for(int i = k - 1; i < n; i++) {
for(int j = k - 1; j < n; j++) {
// compute sum of submatrix
// of order k * k
int sum = dp[i][j];
// remove the submatrix ending at top
if(i >= k) {
sum -= dp[i - k][j];
}
// remove the submatrix ending at left
if(j >= k) {
sum -= dp[i][j - k];
}
// add the overlapping submatrix
if(i >= k && j >= k) {
sum += dp[i - k][j - k];
}
// update the maximum sum
ans = max(ans, sum);
}
}
return ans;
}
int main() {
vector<vector<int>> mat = {
{ 1, 2, -1, 4 },
{ -8, -3, 4, 2 },
{ 3, 8, 10, -8 },
{ -4, -1, 1, 7 } };
int k = 3;
cout << maximumSum(mat, k);
return 0;
}
// Function to find the submatrix of
// order k * k with maximum sum of elements
import java.util.*;
class GfG {
// Function to find the submatrix of
// order k * k with maximum sum of elements
static int maximumSum(int[][] mat, int k) {
int n = mat.length;
// create 2d array to store sum
// elements of submatrices
int[][] dp = new int[n][n];
// calculate the sum of submatrices
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// add the current element
dp[i][j] = mat[i][j];
// add the submatrix ending at left
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
// add the submatrix ending at top
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
// remove the overlapping submatrix
if (i > 0 && j > 0) {
dp[i][j] -= dp[i - 1][j - 1];
}
}
}
// to store the answer
int ans = Integer.MIN_VALUE;
// generate all possible submatrices
// of order k * k
for (int i = k - 1; i < n; i++) {
for (int j = k - 1; j < n; j++) {
// compute sum of submatrix
// of order k * k
int sum = dp[i][j];
// remove the submatrix ending at top
if (i >= k) {
sum -= dp[i - k][j];
}
// remove the submatrix ending at left
if (j >= k) {
sum -= dp[i][j - k];
}
// add the overlapping submatrix
if (i >= k && j >= k) {
sum += dp[i - k][j - k];
}
// update the maximum sum
ans = Math.max(ans, sum);
}
}
return ans;
}
public static void main(String[] args) {
int[][] mat = {
{ 1, 2, -1, 4 },
{ -8, -3, 4, 2 },
{ 3, 8, 10, -8 },
{ -4, -1, 1, 7 }
};
int k = 3;
System.out.println(maximumSum(mat, k));
}
}
# Function to find the submatrix of
# order k * k with maximum sum of elements.
def maximumSum(mat, k):
n = len(mat)
# create 2d array to store sum
# elements of submatrices
dp = [[0 for _ in range(n)] for _ in range(n)]
# calculate the sum of submatrices
for i in range(n):
for j in range(n):
# add the current element
dp[i][j] = mat[i][j]
# add the submatrix ending at left
if j > 0:
dp[i][j] += dp[i][j - 1]
# add the submatrix ending at top
if i > 0:
dp[i][j] += dp[i - 1][j]
# remove the overlapping submatrix
if i > 0 and j > 0:
dp[i][j] -= dp[i - 1][j - 1]
# to store the answer
ans = -float('inf')
# generate all possible submatrices
# of order k * k
for i in range(k - 1, n):
for j in range(k - 1, n):
# compute sum of submatrix
# of order k * k
sum_val = dp[i][j]
# remove the submatrix ending at top
if i >= k:
sum_val -= dp[i - k][j]
# remove the submatrix ending at left
if j >= k:
sum_val -= dp[i][j - k]
# add the overlapping submatrix
if i >= k and j >= k:
sum_val += dp[i - k][j - k]
# update the maximum sum
ans = max(ans, sum_val)
return ans
if __name__ == "__main__":
mat = [
[ 1, 2, -1, 4 ],
[ -8, -3, 4, 2 ],
[ 3, 8, 10, -8 ],
[ -4, -1, 1, 7 ]
]
k = 3
print(maximumSum(mat, k))
// Function to find the submatrix of
// order k * k with maximum sum of elements
using System;
using System.Collections.Generic;
class GfG {
// Function to find the submatrix of
// order k * k with maximum sum of elements
static int maximumSum(List<List<int>> mat, int k) {
int n = mat.Count;
// create 2d array to store sum
// elements of submatrices
List<List<int>> dp = new List<List<int>>();
for (int i = 0; i < n; i++) {
List<int> row = new List<int>();
for (int j = 0; j < n; j++) {
row.Add(0);
}
dp.Add(row);
}
// calculate the sum of submatrices
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// add the current element
dp[i][j] = mat[i][j];
// add the submatrix ending at left
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
// add the submatrix ending at top
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
// remove the overlapping submatrix
if (i > 0 && j > 0) {
dp[i][j] -= dp[i - 1][j - 1];
}
}
}
// to store the answer
int ans = int.MinValue;
// generate all possible submatrices
// of order k * k
for (int i = k - 1; i < n; i++) {
for (int j = k - 1; j < n; j++) {
// compute sum of submatrix
// of order k * k
int sum = dp[i][j];
// remove the submatrix ending at top
if (i >= k) {
sum -= dp[i - k][j];
}
// remove the submatrix ending at left
if (j >= k) {
sum -= dp[i][j - k];
}
// add the overlapping submatrix
if (i >= k && j >= k) {
sum += dp[i - k][j - k];
}
// update the maximum sum
ans = Math.Max(ans, sum);
}
}
return ans;
}
static void Main() {
List<List<int>> mat = new List<List<int>> {
new List<int> { 1, 2, -1, 4 },
new List<int> { -8, -3, 4, 2 },
new List<int> { 3, 8, 10, -8 },
new List<int> { -4, -1, 1, 7 }
};
int k = 3;
Console.WriteLine(maximumSum(mat, k));
}
}
// Function to find the submatrix of
// order k * k with maximum sum of elements.
function maximumSum(mat, k) {
let n = mat.length;
// create 2d array to store sum
// elements of submatrices
let dp = new Array(n);
for (let i = 0; i < n; i++) {
dp[i] = new Array(n).fill(0);
}
// calculate the sum of submatrices
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
// add the current element
dp[i][j] = mat[i][j];
// add the submatrix ending at left
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
// add the submatrix ending at top
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
// remove the overlapping submatrix
if (i > 0 && j > 0) {
dp[i][j] -= dp[i - 1][j - 1];
}
}
}
// to store the answer
let ans = -Infinity;
// generate all possible submatrices
// of order k * k
for (let i = k - 1; i < n; i++) {
for (let j = k - 1; j < n; j++) {
// compute sum of submatrix
// of order k * k
let sum = dp[i][j];
// remove the submatrix ending at top
if (i >= k) {
sum -= dp[i - k][j];
}
// remove the submatrix ending at left
if (j >= k) {
sum -= dp[i][j - k];
}
// add the overlapping submatrix
if (i >= k && j >= k) {
sum += dp[i - k][j - k];
}
// update the maximum sum
ans = Math.max(ans, sum);
}
}
return ans;
}
let mat = [
[ 1, 2, -1, 4 ],
[ -8, -3, 4, 2 ],
[ 3, 8, 10, -8 ],
[ -4, -1, 1, 7 ]
];
let k = 3;
console.log(maximumSum(mat, k));
Output
20
Related Articles:
Given an n x n square matrix, find sum of all sub-squares of size k x k
Maximum sum rectangle in a 2D matrix
