Given a 2D array, find the maximum sum submatrix in it. For example, in the following 2D array, the maximum sum submatrix is highlighted with blue rectangle and sum of all elements in this submatrix is 29.

This problem is mainly an extension of Largest Sum Contiguous Subarray for 1D array.
The Naive Solution for this problem is to check every possible rectangle in the given 2D array. This solution requires 6 nested loops –
- 4 for start and end coordinate of the 2 axis O(n4)
- and 2 for the summation of the sub-matrix O(n2).
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void maxMatrixSum(vector<vector< int > >& matrix)
{
int n = matrix.size();
int m = matrix[0].size();
int maxsum = INT_MIN;
int top = 0, bottom = 0, left = 0, right = 0;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < m; j++) {
for ( int k = 0; k < n; k++) {
for ( int l = 0; l < m; l++) {
int curr = 0;
for ( int x = i; x <= k; x++) {
for ( int y = j; y <= l; y++) {
curr += matrix[x][y];
}
}
if (curr > maxsum) {
maxsum = curr;
top = i;
left = j;
right = k;
bottom = l;
}
}
}
}
}
cout << "( Top , Left )"
<< "( " << top << " , " << left << " )" << endl;
cout << "( Bottom , Right )"
<< "( " << bottom << " , " << right << " )"
<< endl;
cout << "The sum of this rectangle is: " << maxsum
<< endl;
}
int main()
{
vector<vector< int > > v = { { 1, 2, -1, -4, -20 },
{ -8, -3, 4, 2, 1 },
{ 3, 8, 10, 1, 3 },
{ -4, -1, 1, 7, -6 } };
maxMatrixSum(v);
return 0;
}
|
Java
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG {
public static void maxMatrixSum( int [][] matrix)
{
int n = matrix.length;
int m
= matrix[ 0 ].length;
int maxsum = - 999999999 ;
int top = 0 , bottom = 0 , left = 0 , right = 0 ;
for ( int i = 0 ; i < n;
i++) {
for ( int j = 0 ; j < m;
j++) {
for ( int k = 0 ; k < n;
k++) {
for ( int l = 0 ; l < m;
l++) {
int curr = 0 ;
for ( int x = i; x <= k;
x++) {
for ( int y = j; y <= l;
y++) {
curr += matrix[x][y];
}
}
if (curr > maxsum) {
maxsum = curr;
top = i;
left = j;
right = k;
bottom = l;
}
}
}
}
}
System.out.println( "Top , Left ) ( " + top + " , "
+ left + " )" );
System.out.println( "Bottom , Right) ( " + bottom
+ " , " + right + " )" );
System.out.println( "The sum of the rectangle is: "
+ maxsum);
}
public static void main(String[] args)
{
int arr[][] = new int [][] { { 1 , 2 , - 1 , - 4 , - 20 },
{ - 8 , - 3 , 4 , 2 , 1 },
{ 3 , 8 , 10 , 1 , 3 },
{ - 4 , - 1 , 1 , 7 , - 6 } };
maxMatrixSum(arr);
}
}
|
Python3
def max_matrix_sum(matrix):
n = len (matrix)
m = len (matrix[ 0 ])
max_sum = float ( '-inf' )
top = 0
bottom = 0
left = 0
right = 0
for i in range (n):
for j in range (m):
for k in range (n):
for l in range (m):
curr = 0
for x in range (i, k + 1 ):
for y in range (j, l + 1 ):
curr + = matrix[x][y]
if curr > max_sum:
max_sum = curr
top = i
left = j
right = l
bottom = k
print ( "(Top, Left): ({}, {})" . format (top, left))
print ( "(Bottom, Right): ({}, {})" . format (bottom, right))
print ( "The sum of this rectangle is:" , max_sum)
matrix = [[ 1 , 2 , - 1 , - 4 , - 20 ],
[ - 8 , - 3 , 4 , 2 , 1 ],
[ 3 , 8 , 10 , 1 , 3 ],
[ - 4 , - 1 , 1 , 7 , - 6 ]]
max_matrix_sum(matrix)
|
C#
using System;
class GFG {
static void MaxMatrixSum( int [][] matrix)
{
int n
= matrix.Length;
int m = matrix[0].Length;
int maxsum
= int .MinValue;
int top = 0, bottom = 0, left = 0,
right
= 0;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < m; j++) {
for ( int k = i; k < n; k++) {
for ( int l = j; l < m; l++) {
int curr
= 0;
for ( int x = i; x <= k; x++) {
for ( int y = j; y <= l; y++) {
curr += matrix[x][y];
}
}
if (curr > maxsum) {
maxsum = curr;
top = i;
left = j;
right = l;
bottom = k;
}
}
}
}
}
Console.WriteLine( "(Top, Left) (" + top + ", "
+ left + ")" );
Console.WriteLine( "(Bottom, Right) (" + bottom
+ ", " + right + ")" );
Console.WriteLine( "The sum of this rectangle is: "
+ maxsum);
}
static void Main()
{
int [][] v
= new int [][] { new int [] { 1, 2, -1, -4, -20 },
new int [] { -8, -3, 4, 2, 1 },
new int [] { 3, 8, 10, 1, 3 },
new int [] { -4, -1, 1, 7,
-6 } };
MaxMatrixSum(v);
}
}
|
Javascript
function maxMatrixSum(matrix) {
const n = matrix.length;
const m = matrix[0].length;
let maxsum = Number.MIN_SAFE_INTEGER;
let top = 0, bottom = 0, left = 0, right = 0;
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
for (let k = i; k < n; k++) {
for (let l = j; l < m; l++) {
let curr = 0;
for (let x = i; x <= k; x++) {
for (let y = j; y <= l; y++) {
curr += matrix[x][y];
}
}
if (curr > maxsum) {
maxsum = curr;
top = i;
left = j;
bottom = k;
right = l;
}
}
}
}
}
console.log(`( Top , Left ) ( ${top} , ${left} )`);
console.log(`( Bottom , Right ) ( ${bottom} , ${right} )`);
console.log(`The sum of this rectangle is: ${maxsum}`);
}
const matrix = [
[1, 2, -1, -4, -20],
[-8, -3, 4, 2, 1],
[3, 8, 10, 1, 3],
[-4, -1, 1, 7, -6]
];
maxMatrixSum(matrix);
|
Output:
( Top , Left )( 1 , 1 )
( Bottom , Right )( 3 , 3 )
The sum of this rectangle is: 29
Time Complexity: O(n^3 * m^3) where n is the number of rows and m is the numbr of columns in the given matrix.
Efficient Approach –
Kadane’s algorithm for 1D array can be used to reduce the time complexity to O(n^3). The idea is to fix the left and right columns one by one and find the maximum sum contiguous rows for every left and right column pair. We basically find top and bottom row numbers (which have maximum sum) for every fixed left and right column pair. To find the top and bottom row numbers, calculate the sum of elements in every row from left to right and store these sums in an array say temp[]. So temp[i] indicates sum of elements from left to right in row i. If we apply Kadane’s 1D algorithm on temp[], and get the maximum sum subarray of temp, this maximum sum would be the maximum possible sum with left and right as boundary columns. To get the overall maximum sum, we compare this sum with the maximum sum so far.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
#define ROW 4
#define COL 5
int kadane( int * arr, int * start, int * finish, int n)
{
int sum = 0, maxSum = INT_MIN, i;
*finish = -1;
int local_start = 0;
for (i = 0; i < n; ++i) {
sum += arr[i];
if (sum < 0) {
sum = 0;
local_start = i + 1;
}
else if (sum > maxSum) {
maxSum = sum;
*start = local_start;
*finish = i;
}
}
if (*finish != -1)
return maxSum;
maxSum = arr[0];
*start = *finish = 0;
for (i = 1; i < n; i++) {
if (arr[i] > maxSum) {
maxSum = arr[i];
*start = *finish = i;
}
}
return maxSum;
}
void findMaxSum( int M[][COL])
{
int maxSum = INT_MIN, finalLeft, finalRight, finalTop,
finalBottom;
int left, right, i;
int temp[ROW], sum, start, finish;
for (left = 0; left < COL; ++left) {
memset (temp, 0, sizeof (temp));
for (right = left; right < COL; ++right) {
for (i = 0; i < ROW; ++i)
temp[i] += M[i][right];
sum = kadane(temp, &start, &finish, ROW);
if (sum > maxSum) {
maxSum = sum;
finalLeft = left;
finalRight = right;
finalTop = start;
finalBottom = finish;
}
}
}
cout << "(Top, Left) (" << finalTop << ", " << finalLeft
<< ")" << endl;
cout << "(Bottom, Right) (" << finalBottom << ", "
<< finalRight << ")" << endl;
cout << "Max sum is: " << maxSum << endl;
}
int main()
{
int M[ROW][COL] = { { 1, 2, -1, -4, -20 },
{ -8, -3, 4, 2, 1 },
{ 3, 8, 10, 1, 3 },
{ -4, -1, 1, 7, -6 } };
findMaxSum(M);
return 0;
}
|
C
#include <limits.h>
#include <stdio.h>
#include <string.h>
#define ROW 4
#define COL 5
int kadane( int * arr, int * start, int * finish, int n)
{
int sum = 0, maxSum = INT_MIN, i;
*finish = -1;
int local_start = 0;
for (i = 0; i < n; ++i) {
sum += arr[i];
if (sum < 0) {
sum = 0;
local_start = i + 1;
}
else if (sum > maxSum) {
maxSum = sum;
*start = local_start;
*finish = i;
}
}
if (*finish != -1)
return maxSum;
maxSum = arr[0];
*start = *finish = 0;
for (i = 1; i < n; i++) {
if (arr[i] > maxSum) {
maxSum = arr[i];
*start = *finish = i;
}
}
return maxSum;
}
void findMaxSum( int M[][COL])
{
int maxSum = INT_MIN, finalLeft, finalRight, finalTop,
finalBottom;
int left, right, i;
int temp[ROW], sum, start, finish;
for (left = 0; left < COL; ++left) {
memset (temp, 0, sizeof (temp));
for (right = left; right < COL; ++right) {
for (i = 0; i < ROW; ++i)
temp[i] += M[i][right];
sum = kadane(temp, &start, &finish, ROW);
if (sum > maxSum) {
maxSum = sum;
finalLeft = left;
finalRight = right;
finalTop = start;
finalBottom = finish;
}
}
}
printf ( "(Top, Left) (%d, %d)\n" , finalTop, finalLeft);
printf ( "(Bottom, Right) (%d, %d)\n" , finalBottom,
finalRight);
printf ( "Max sum is: %d\n" , maxSum);
}
int main()
{
int M[ROW][COL] = { { 1, 2, -1, -4, -20 },
{ -8, -3, 4, 2, 1 },
{ 3, 8, 10, 1, 3 },
{ -4, -1, 1, 7, -6 } };
findMaxSum(M);
return 0;
}
|
Java
import java.io.*;
import java.lang.*;
import java.util.*;
class MaximumSumRectangle {
private static int maxSumRectangle( int [][] mat)
{
int m = mat.length;
int n = mat[ 0 ].length;
int preSum[][] = new int [m + 1 ][n];
for ( int i = 0 ; i < m; i++) {
for ( int j = 0 ; j < n; j++) {
preSum[i + 1 ][j] = preSum[i][j] + mat[i][j];
}
}
int maxSum = - 1 ;
int minSum = Integer.MIN_VALUE;
int negRow = 0 , negCol = 0 ;
int rStart = 0 , rEnd = 0 , cStart = 0 , cEnd = 0 ;
for ( int rowStart = 0 ; rowStart < m; rowStart++) {
for ( int row = rowStart; row < m; row++) {
int sum = 0 ;
int curColStart = 0 ;
for ( int col = 0 ; col < n; col++) {
sum += preSum[row + 1 ][col]
- preSum[rowStart][col];
if (sum < 0 ) {
if (minSum < sum) {
minSum = sum;
negRow = row;
negCol = col;
}
sum = 0 ;
curColStart = col + 1 ;
}
else if (maxSum < sum) {
maxSum = sum;
rStart = rowStart;
rEnd = row;
cStart = curColStart;
cEnd = col;
}
}
}
}
if (maxSum == - 1 ) {
System.out.println( "from row - " + negRow
+ " to row - " + negRow);
System.out.println( "from col - " + negCol
+ " to col - " + negCol);
}
else {
System.out.println( "from row - " + rStart
+ " to row - " + rEnd);
System.out.println( "from col - " + cStart
+ " to col - " + cEnd);
}
return maxSum == - 1 ? minSum : maxSum;
}
public static void main(String[] args)
{
int arr[][] = new int [][] { { 1 , 2 , - 1 , - 4 , - 20 },
{ - 8 , - 3 , 4 , 2 , 1 },
{ 3 , 8 , 10 , 1 , 3 },
{ - 4 , - 1 , 1 , 7 , - 6 } };
System.out.println(maxSumRectangle(arr));
}
}
|
Python3
def kadane(arr, start, finish, n):
Sum = 0
maxSum = - 999999999999
i = None
finish[ 0 ] = - 1
local_start = 0
for i in range (n):
Sum + = arr[i]
if Sum < 0 :
Sum = 0
local_start = i + 1
elif Sum > maxSum:
maxSum = Sum
start[ 0 ] = local_start
finish[ 0 ] = i
if finish[ 0 ] ! = - 1 :
return maxSum
maxSum = arr[ 0 ]
start[ 0 ] = finish[ 0 ] = 0
for i in range ( 1 , n):
if arr[i] > maxSum:
maxSum = arr[i]
start[ 0 ] = finish[ 0 ] = i
return maxSum
def findMaxSum(M):
global ROW, COL
maxSum, finalLeft = - 999999999999 , None
finalRight, finalTop, finalBottom = None , None , None
left, right, i = None , None , None
temp = [ None ] * ROW
Sum = 0
start = [ 0 ]
finish = [ 0 ]
for left in range (COL):
temp = [ 0 ] * ROW
for right in range (left, COL):
for i in range (ROW):
temp[i] + = M[i][right]
Sum = kadane(temp, start, finish, ROW)
if Sum > maxSum:
maxSum = Sum
finalLeft = left
finalRight = right
finalTop = start[ 0 ]
finalBottom = finish[ 0 ]
print ( "(Top, Left)" , "(" , finalTop,
finalLeft, ")" )
print ( "(Bottom, Right)" , "(" , finalBottom,
finalRight, ")" )
print ( "Max sum is:" , maxSum)
ROW = 4
COL = 5
M = [[ 1 , 2 , - 1 , - 4 , - 20 ],
[ - 8 , - 3 , 4 , 2 , 1 ],
[ 3 , 8 , 10 , 1 , 3 ],
[ - 4 , - 1 , 1 , 7 , - 6 ]]
findMaxSum(M)
|
C#
using System;
class GFG {
public static int [] kadane( int [] a)
{
int [] result = new int [] { int .MinValue, 0, -1 };
int currentSum = 0;
int localStart = 0;
for ( int i = 0; i < a.Length; i++) {
currentSum += a[i];
if (currentSum < 0) {
currentSum = 0;
localStart = i + 1;
}
else if (currentSum > result[0]) {
result[0] = currentSum;
result[1] = localStart;
result[2] = i;
}
}
if (result[2] == -1) {
result[0] = 0;
for ( int i = 0; i < a.Length; i++) {
if (a[i] > result[0]) {
result[0] = a[i];
result[1] = i;
result[2] = i;
}
}
}
return result;
}
public static void findMaxSubMatrix( int [, ] a)
{
int cols = a.GetLength(1);
int rows = a.GetLength(0);
int [] currentResult;
int maxSum = int .MinValue;
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
for ( int leftCol = 0; leftCol < cols; leftCol++) {
int [] tmp = new int [rows];
for ( int rightCol = leftCol; rightCol < cols;
rightCol++) {
for ( int i = 0; i < rows; i++) {
tmp[i] += a[i, rightCol];
}
currentResult = kadane(tmp);
if (currentResult[0] > maxSum) {
maxSum = currentResult[0];
left = leftCol;
top = currentResult[1];
right = rightCol;
bottom = currentResult[2];
}
}
}
Console.Write( "MaxSum: " + maxSum + ", range: [("
+ left + ", " + top + ")(" + right
+ ", " + bottom + ")]" );
}
public static void Main()
{
int [, ] arr = { { 1, 2, -1, -4, -20 },
{ -8, -3, 4, 2, 1 },
{ 3, 8, 10, 1, 3 },
{ -4, -1, 1, 7, -6 } };
findMaxSubMatrix(arr);
}
}
|
Javascript
<script>
var ROW = 4
var COL = 5
var start = 0
var finish = 0
function kadane(arr, n)
{
var sum = 0, maxSum = -1000000000, i;
finish = -1;
var local_start = 0;
for (i = 0; i < n; ++i)
{
sum += arr[i];
if (sum < 0)
{
sum = 0;
local_start = i + 1;
}
else if (sum > maxSum)
{
maxSum = sum;
start = local_start;
finish = i;
}
}
if (finish != -1)
return maxSum;
maxSum = arr[0];
start = finish = 0;
for (i = 1; i < n; i++)
{
if (arr[i] > maxSum)
{
maxSum = arr[i];
start = finish = i;
}
}
return maxSum;
}
function findMaxSum(M)
{
var maxSum = -1000000000,
finalLeft=0,
finalRight=0,
finalTop=0,
finalBottom=0;
var left, right, i;
var temp = Array(ROW);
var sum;
for (left = 0; left < COL; ++left) {
temp = Array(ROW).fill(0);
for (right = left; right < COL; ++right) {
for (i = 0; i < ROW; ++i)
temp[i] += M[i][right];
sum = kadane(temp, ROW);
if (sum > maxSum) {
maxSum = sum;
finalLeft = left;
finalRight = right;
finalTop = start;
finalBottom = finish;
}
}
}
document.write( "(Top, Left) ("
+ finalTop + ", "
+ finalLeft
+ ")" + "<br>" );
document.write( "(Bottom, Right) ("
+ finalBottom + ", "
+ finalRight + ")" + "<br>" );
document.write( "Max sum is: " + maxSum + "<br>" );
}
var M = [ [ 1, 2, -1, -4, -20 ],
[ -8, -3, 4, 2, 1 ],
[ 3, 8, 10, 1, 3 ],
[ -4, -1, 1, 7, -6 ] ];
findMaxSum(M);
</script>
|
Output
(Top, Left) (1, 1)
(Bottom, Right) (3, 3)
Max sum is: 29
Time Complexity: O(c*c*r), where c represents the number of columns and r represents the number of rows in the given matrix.
Auxiliary Space: O(r), where r represents the number of rows in the given matrix.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
19 Sep, 2023
Like Article
Save Article