Maximum sum rectangle in a 2D matrix | DP-27 - GeeksforGeeks

11 Nov, 2021
Given a 2D array, find the maximum sum subarray in it. For example, in the following 2D array, the maximum sum subarray is highlighted with blue rectangle and sum of this subarray 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).
The overall time complexity of this solution would be O(n6).
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.
C++
C
Java
Python3
C#
Javascript
// Program to find maximum sum subarray// in a given 2D array#include <bits/stdc++.h>using namespace std; #define ROW 4#define COL 5 // Implementation of Kadane's algorithm for// 1D array. The function returns the maximum// sum and stores starting and ending indexes// of the maximum sum subarray at addresses// pointed by start and finish pointers// respectively.int kadane(int* arr, int* start, int* finish, int n){    // initialize sum, maxSum and    int sum = 0, maxSum = INT_MIN, i;     // Just some initial value to check    // for all negative values case    *finish = -1;     // local variable    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;        }    }     // There is at-least one    // non-negative number    if (*finish != -1)        return maxSum;     // Special Case: When all numbers    // in arr[] are negative    maxSum = arr[0];    *start = *finish = 0;     // Find the maximum element in array    for (i = 1; i < n; i++)    {        if (arr[i] > maxSum)        {            maxSum = arr[i];            *start = *finish = i;        }    }    return maxSum;} // The main function that finds// maximum sum rectangle in M[][]void findMaxSum(int M[][COL]){    // Variables to store the final output    int maxSum = INT_MIN,                 finalLeft,                 finalRight,                 finalTop,                 finalBottom;     int left, right, i;    int temp[ROW], sum, start, finish;     // Set the left column    for (left = 0; left < COL; ++left) {        // Initialize all elements of temp as 0        memset(temp, 0, sizeof(temp));         // Set the right column for the left        // column set by outer loop        for (right = left; right < COL; ++right) {             // Calculate sum between current left            // and right for every row 'i'            for (i = 0; i < ROW; ++i)                temp[i] += M[i][right];             // Find the maximum sum subarray in temp[].            // The kadane() function also sets values            // of start and finish. So 'sum' is sum of            // rectangle between (start, left) and            // (finish, right) which is the maximum sum            // with boundary columns strictly as left            // and right.            sum = kadane(temp, &start, &finish, ROW);             // Compare sum with maximum sum so far.            // If sum is more, then update maxSum and            // other output values            if (sum > maxSum) {                maxSum = sum;                finalLeft = left;                finalRight = right;                finalTop = start;                finalBottom = finish;            }        }    }     // Print final values    cout << "(Top, Left) ("         << finalTop << ", "         << finalLeft         << ")" << endl;    cout << "(Bottom, Right) ("         << finalBottom << ", "         << finalRight << ")" << endl;    cout << "Max sum is: " << maxSum << endl;} // Driver Codeint 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 } };     // Function call    findMaxSum(M);     return 0;} // This code is contributed by// rathbhupendra
// Program to find maximum sum subarray// in a given 2D array#include <limits.h>#include <stdio.h>#include <string.h>#define ROW 4#define COL 5 // Implementation of Kadane's algorithm// for 1D array. The function returns the// maximum sum and stores starting and// ending indexes of the maximum sum subarray// at addresses pointed by start and finish// pointers respectively.int kadane(int* arr, int* start,           int* finish, int n){    // initialize sum, maxSum and    int sum = 0, maxSum = INT_MIN, i;     // Just some initial value to check for all negative    // values case    *finish = -1;     // local variable    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;        }    }     // There is at-least one non-negative number    if (*finish != -1)        return maxSum;     // Special Case: When all numbers in arr[]    // are negative    maxSum = arr[0];    *start = *finish = 0;     // Find the maximum element in array    for (i = 1; i < n; i++)    {        if (arr[i] > maxSum)        {            maxSum = arr[i];            *start = *finish = i;        }    }    return maxSum;} // The main function that finds maximum// sum rectangle in// M[][]void findMaxSum(int M[][COL]){    // Variables to store the final output    int maxSum = INT_MIN,                 finalLeft,                 finalRight,                 finalTop,                 finalBottom;     int left, right, i;    int temp[ROW], sum, start, finish;     // Set the left column    for (left = 0; left < COL; ++left)    {        // Initialize all elements of temp as 0        memset(temp, 0, sizeof(temp));         // Set the right column for the left column set by        // outer loop        for (right = left; right < COL; ++right) {            // Calculate sum between current left and right            // for every row 'i'            for (i = 0; i < ROW; ++i)                temp[i] += M[i][right];             // Find the maximum sum subarray in temp[].            // The kadane() function also sets values of            // start and finish.  So 'sum' is sum of            // rectangle between (start, left) and (finish,            //  right) which is the maximum sum with boundary            //  columns strictly as left and right.            sum = kadane(temp, &start, &finish, ROW);             // Compare sum with maximum sum so far. If sum            // is more, then update maxSum and other output            // values            if (sum > maxSum)            {                maxSum = sum;                finalLeft = left;                finalRight = right;                finalTop = start;                finalBottom = finish;            }        }    }     // Print final values    printf("(Top, Left) (%d, %d)\n", finalTop, finalLeft);    printf("(Bottom, Right) (%d, %d)\n", finalBottom,           finalRight);    printf("Max sum is: %d\n", maxSum);} // Driver Codeint 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 } };     // Function call    findMaxSum(M);     return 0;}
// Java Program to find max sum rectangular submatrix import java.util.*;import java.lang.*;import java.io.*; class MaximumSumRectangle{     // Function to find maximum sum rectangular    // submatrix    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;                    }                }            }        }         // Printing final values        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;    }     // Driver Code    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 } };               // Function call        System.out.println(maxSumRectangle(arr));    }} // This code is contributed by Nayanava De
# Python3 program to find maximum sum# subarray in a given 2D array # Implementation of Kadane's algorithm# for 1D array. The function returns the# maximum sum and stores starting and# ending indexes of the maximum sum subarray# at addresses pointed by start and finish# pointers respectively.  def kadane(arr, start, finish, n):     # initialize sum, maxSum and    Sum = 0    maxSum = -999999999999    i = None     # Just some initial value to check    # for all negative values case    finish[0] = -1     # local variable    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     # There is at-least one    # non-negative number    if finish[0] != -1:        return maxSum     # Special Case: When all numbers    # in arr[] are negative    maxSum = arr[0]    start[0] = finish[0] = 0     # Find the maximum element in array    for i in range(1, n):        if arr[i] > maxSum:            maxSum = arr[i]            start[0] = finish[0] = i    return maxSum # The main function that finds maximum# sum rectangle in M[][]  def findMaxSum(M):    global ROW, COL     # Variables to store the final output    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]     # Set the left column    for left in range(COL):         # Initialize all elements of temp as 0        temp = [0] * ROW         # Set the right column for the left        # column set by outer loop        for right in range(left, COL):             # Calculate sum between current left            # and right for every row 'i'            for i in range(ROW):                temp[i] += M[i][right]             # Find the maximum sum subarray in            # temp[]. The kadane() function also            # sets values of start and finish.            # So 'sum' is sum of rectangle between            # (start, left) and (finish, right) which            # is the maximum sum with boundary columns            # strictly as left and right.            Sum = kadane(temp, start, finish, ROW)             # Compare sum with maximum sum so far.            # If sum is more, then update maxSum            # and other output values            if Sum > maxSum:                maxSum = Sum                finalLeft = left                finalRight = right                finalTop = start[0]                finalBottom = finish[0]     # Prfinal values    print("(Top, Left)", "(", finalTop,          finalLeft, ")")    print("(Bottom, Right)", "(", finalBottom,          finalRight, ")")    print("Max sum is:", maxSum)  # Driver CodeROW = 4COL = 5M = [[1, 2, -1, -4, -20],     [-8, -3, 4, 2, 1],     [3, 8, 10, 1, 3],     [-4, -1, 1, 7, -6]] # Function callfindMaxSum(M) # This code is contributed by PranchalK
// C# Given a 2D array, find the// maximum sum subarray in itusing System; class GFG {     /**     * To find maxSum in 1d array     *     * return {maxSum, left, right}     */    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;            }        }         // all numbers in a are negative        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;    }     /**    * To find and print maxSum,     (left, top),(right, bottom)    */    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 + ")]");    }     // Driver Code    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 } };               // Function call        findMaxSubMatrix(arr);    }} // This code is contributed// by PrinciRaj1992
<script> // Program to find maximum sum subarray// in a given 2D array var ROW = 4var COL = 5var start = 0var finish = 0 // Implementation of Kadane's algorithm for// 1D array. The function returns the maximum// sum and stores starting and ending indexes// of the maximum sum subarray at addresses// pointed by start and finish pointers// respectively.function kadane(arr, n){    // initialize sum, maxSum and    var sum = 0, maxSum = -1000000000, i;     // Just some initial value to check    // for all negative values case    finish = -1;     // local variable    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;        }    }     // There is at-least one    // non-negative number    if (finish != -1)        return maxSum;     // Special Case: When all numbers    // in arr[] are negative    maxSum = arr[0];    start = finish = 0;     // Find the maximum element in array    for (i = 1; i < n; i++)    {        if (arr[i] > maxSum)        {            maxSum = arr[i];            start = finish = i;        }    }    return maxSum;} // The main function that finds// maximum sum rectangle in M[][]function findMaxSum(M){    // Variables to store the final output    var maxSum = -1000000000,                 finalLeft=0,                 finalRight=0,                 finalTop=0,                 finalBottom=0;     var left, right, i;    var temp = Array(ROW);    var sum;     // Set the left column    for (left = 0; left < COL; ++left) {        // Initialize all elements of temp as 0        temp = Array(ROW).fill(0);         // Set the right column for the left        // column set by outer loop        for (right = left; right < COL; ++right) {             // Calculate sum between current left            // and right for every row 'i'            for (i = 0; i < ROW; ++i)                temp[i] += M[i][right];             // Find the maximum sum subarray in temp[].            // The kadane() function also sets values            // of start and finish. So 'sum' is sum of            // rectangle between (start, left) and            // (finish, right) which is the maximum sum            // with boundary columns strictly as left            // and right.            sum = kadane(temp, ROW);             // Compare sum with maximum sum so far.            // If sum is more, then update maxSum and            // other output values            if (sum > maxSum) {                maxSum = sum;                finalLeft = left;                finalRight = right;                finalTop = start;                finalBottom = finish;            }        }    }     // Print final values    document.write("(Top, Left) ("         + finalTop + ", "         + finalLeft         + ")" + "<br>");    document.write("(Bottom, Right) ("         + finalBottom + ", "         + finalRight + ")" + "<br>");    document.write("Max sum is: " + maxSum + "<br>");} // Driver Codevar M = [ [ 1, 2, -1, -4, -20 ],                    [ -8, -3, 4, 2, 1 ],                    [ 3, 8, 10, 1, 3 ],                    [ -4, -1, 1, 7, -6 ] ];// Function callfindMaxSum(M); // This code is contributed by rutvik_56.</script>
(Top, Left) (1, 1)
(Bottom, Right) (3, 3)
Max sum is: 29
Time Complexity: O(n3)
This article is compiled by Aashish Barnwal. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Gaurav Kumar 33
princiraj1992
PranchalKatiyar
rathbhupendra
tonyshen
kushagra98
uchiha1101
rutvik_56
Accolite
Amazon
FactSet
Samsung
Arrays
Dynamic Programming
Matrix
Misc
Accolite
Amazon
Samsung
FactSet
Misc
Arrays
Dynamic Programming
Misc
Matrix
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Maximum and minimum of an array using minimum number of comparisons
Top 50 Array Coding Problems for Interviews
Stack Data Structure (Introduction and Program)
Introduction to Arrays
Multidimensional Arrays in Java
0-1 Knapsack Problem | DP-10
Program for Fibonacci numbers
Longest Common Subsequence | DP-4
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16