Open In App

Maximum sum submatrix

Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisite: Kadane’s algorithm

Given a 2D array arr[][] of dimension N*M, the task is to find the maximum sum sub-matrix from the matrix arr[][].

Examples:

Input: arr[][] = {{0, -2, -7, 0 },  { 9, 2, -6, 2 }, { -4, 1, -4, 1 }, { -1, 8, 0, -2}}
Output: 15
Explanation: The submatrix {{9, 2}, {-4, 1}, {-1, 8}} has a sum 15, which is the maximum sum possible.

Input: arr[][] = {{1, 2}, {-5, -7}}
Output: 3

Naive Approach: The simplest approach is to generate all possible submatrices from the given matrix and calculate their sum. Finally, print the maximum sum obtained.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to find maximum sum submatrix
void maxSubmatrixSum(
    vector<vector<int> > matrix)
{
    // Stores the number of rows
    // and columns in the matrix
    int r = matrix.size();
    int c = matrix[0].size();
  
    // Stores maximum submatrix sum
    int maxSubmatrix = 0;
  
    // Take each row as starting row
    for (int i = 0; i < r; i++) {
  
        // Take each column as the
        // starting column
        for (int j = 0; j < c; j++) {
  
            // Take each row as the
            // ending row
            for (int k = i; k < r; k++) {
  
                // Take each column as
                // the ending column
                for (int l = j; l < c; l++) {
  
                    // Stores the sum of submatrix
                    // having topleft index(i, j)
                    // and bottom right index (k, l)
                    int sumSubmatrix = 0;
  
                    // Iterate the submatrix
                    // row-wise and calculate its sum
                    for (int m = i; m <= k; m++) {
                        for (int n = j; n <= l; n++) {
                            sumSubmatrix += matrix[m][n];
                        }
                    }
  
                    // Update the maximum sum
                    maxSubmatrix
                        = max(maxSubmatrix,
                              sumSubmatrix);
                }
            }
        }
    }
  
    // Print the answer
    cout << maxSubmatrix;
}
  
// Driver Code
int main()
{
    vector<vector<int> > matrix = { { 0, -2, -7, 0 },
                                    { 9, 2, -6, 2 },
                                    { -4, 1, -4, 1 },
                                    { -1, 8, 0, -2 } };
  
    maxSubmatrixSum(matrix);
  
    return 0;
}


Java




// Java program for the above approach
import java.util.*;
class GFG
{
  
// Function to find maximum sum submatrix
static void maxSubmatrixSum(int[][] matrix)
{
    
    // Stores the number of rows
    // and columns in the matrix
    int r = matrix.length;
    int c = matrix[0].length;
  
    // Stores maximum submatrix sum
    int maxSubmatrix = 0;
  
    // Take each row as starting row
    for (int i = 0; i < r; i++) {
  
        // Take each column as the
        // starting column
        for (int j = 0; j < c; j++) {
  
            // Take each row as the
            // ending row
            for (int k = i; k < r; k++) {
  
                // Take each column as
                // the ending column
                for (int l = j; l < c; l++) {
  
                    // Stores the sum of submatrix
                    // having topleft index(i, j)
                    // and bottom right index (k, l)
                    int sumSubmatrix = 0;
  
                    // Iterate the submatrix
                    // row-wise and calculate its sum
                    for (int m = i; m <= k; m++) {
                        for (int n = j; n <= l; n++) {
                            sumSubmatrix += matrix[m][n];
                        }
                    }
  
                    // Update the maximum sum
                    maxSubmatrix
                        = Math.max(maxSubmatrix,
                              sumSubmatrix);
                }
            }
        }
    }
  
    // Print the answer
    System.out.println(maxSubmatrix);
}
    
// Driver Code
public static void main(String[] args)
{
    int[][] matrix = { { 0, -2, -7, 0 },
                        { 9, 2, -6, 2 },
                        { -4, 1, -4, 1 },
                        { -1, 8, 0, -2 } };
  
    maxSubmatrixSum(matrix);
}
}
  
// This code is contributed by susmitakundugoaldanga.


Python3




# Python3 program for the above approach
  
# Function to find maximum sum submatrix
def maxSubmatrixSum(matrix):
    
    # Stores the number of rows
    # and columns in the matrix
    r = len(matrix)
    c = len(matrix[0])
  
    # Stores maximum submatrix sum
    maxSubmatrix = 0
  
    # Take each row as starting row
    for i in range(r):
  
        # Take each column as the
        # starting column
        for j in range(c):
  
            # Take each row as the
            # ending row
            for k in range(i, r):
  
                # Take each column as
                # the ending column
                for l in range(j, c):
  
                    # Stores the sum of submatrix
                    # having topleft index(i, j)
                    # and bottom right index (k, l)
                    sumSubmatrix = 0
  
                    # Iterate the submatrix
                    # row-wise and calculate its sum
                    for m in range(i, k + 1):
                        for n in range(j, l + 1):
                            sumSubmatrix += matrix[m][n]
  
                    # Update the maximum sum
                    maxSubmatrix= max(maxSubmatrix, sumSubmatrix)
  
    # Print the answer
    print (maxSubmatrix)
  
# Driver Code
if __name__ == '__main__':
    matrix = [ [ 0, -2, -7, 0 ],
                [ 9, 2, -6, 2 ],
                [ -4, 1, -4, 1 ],
                [ -1, 8, 0, -2 ] ]
  
    maxSubmatrixSum(matrix)
  
    # This code is contributed by mohit kumar 29.


C#




// C# program to implement 
// the above approach 
using System;
public class GFG
{
// Function to find maximum sum submatrix
static void maxSubmatrixSum(int[,] matrix)
{
    
    // Stores the number of rows
    // and columns in the matrix
    int r = matrix.GetLength(0);
    int c = matrix.GetLength(1);
  
    // Stores maximum submatrix sum
    int maxSubmatrix = 0;
  
    // Take each row as starting row
    for (int i = 0; i < r; i++) {
  
        // Take each column as the
        // starting column
        for (int j = 0; j < c; j++) {
  
            // Take each row as the
            // ending row
            for (int k = i; k < r; k++) {
  
                // Take each column as
                // the ending column
                for (int l = j; l < c; l++) {
  
                    // Stores the sum of submatrix
                    // having topleft index(i, j)
                    // and bottom right index (k, l)
                    int sumSubmatrix = 0;
  
                    // Iterate the submatrix
                    // row-wise and calculate its sum
                    for (int m = i; m <= k; m++) {
                        for (int n = j; n <= l; n++) {
                            sumSubmatrix += matrix[m, n];
                        }
                    }
  
                    // Update the maximum sum
                    maxSubmatrix
                        = Math.Max(maxSubmatrix,
                              sumSubmatrix);
                }
            }
        }
    }
  
    // Print the answer
    Console.WriteLine(maxSubmatrix);
}
  
// Driver Code
public static void Main(String []args)
{
    int[,] matrix = { { 0, -2, -7, 0 },
                        { 9, 2, -6, 2 },
                        { -4, 1, -4, 1 },
                        { -1, 8, 0, -2 } };
  
    maxSubmatrixSum(matrix);
}
}
  
// This code is contributed by sanjoy_62.


Javascript




<script>
  
// Javascript program for the above approach
  
    // Function to find maximum sum submatrix
    function maxSubmatrixSum(matrix) 
    {
  
        // Stores the number of rows
        // and columns in the matrix
        var r = matrix.length;
        var c = matrix[0].length;
  
        // Stores maximum submatrix sum
        var maxSubmatrix = 0;
  
        // Take each row as starting row
        for (i = 0; i < r; i++) {
  
            // Take each column as the
            // starting column
            for (j = 0; j < c; j++) {
  
                // Take each row as the
                // ending row
                for (k = i; k < r; k++) {
  
                    // Take each column as
                    // the ending column
                    for (l = j; l < c; l++) {
  
                        // Stores the sum of submatrix
                        // having topleft index(i, j)
                        // and bottom right index (k, l)
                        var sumSubmatrix = 0;
  
                        // Iterate the submatrix
                        // row-wise and calculate its sum
                        for (m = i; m <= k; m++) {
                            for (n = j; n <= l; n++) {
                                sumSubmatrix += matrix[m][n];
                            }
                        }
  
                        // Update the maximum sum
                        maxSubmatrix = Math.max(maxSubmatrix, 
                        sumSubmatrix);
                    }
                }
            }
        }
  
        // Print the answer
        document.write(maxSubmatrix);
    }
  
    // Driver Code
      
        var matrix = [ [ 0, -2, -7, 0 ],
        [ 9, 2, -6, 2 ], 
        [ -4, 1, -4, 1 ], 
        [ -1, 8, 0, -2 ] ];
  
        maxSubmatrixSum(matrix);
  
// This code contributed by umadevi9616
  
</script>


Output: 

15

 

Time Complexity: O(N6)
Auxiliary Space: O(1)

Efficient Approach using Kadane’s Algorithm: The above approach can be optimized using the following observations:

  • Fix starting and ending column of the required sub-matrix say start and end respectively.
  • Now, iterate each row and add row sum from starting to ending column to sumSubmatrix and insert this in an array. After iterating each row, perform Kadane’s Algorithm on this newly created array. If the sum obtained by applying Kadane’s algorithm is greater than the overall maximum sum, update the overall maximum sum.
  • In the above step, the row sum from starting to ending column can be calculated in constant time by creating an auxiliary matrix of size N*M containing the prefix sum of each row.

Follow the steps below to solve the problem:

  • Initialize a variable, say maxSum as INT_MIN, to store the maximum subarray sum.
  • Create a matrix prefMatrix[N][M] that stores the prefix array sum of every row of the given matrix.
  • Traverse the matrix row-wise using i as the row index and j as the column index and perform the following steps:
    • If the value of i is 0, then set prefMatrix[i][j] = A[i][j].
    • Otherwise, set prefMatrix[i][j] = prefMatrix[i][j – 1] + A[i][j].
  • Now for all possible combinations of starting and ending index of the columns of submatrix over the range [0, M] perform the following steps:
    • Initialize an auxiliary array A[] to stores the maximum sum for each row of the current submatrix.
    • Find the sum from starting to ending column using prefMatrix as follows:
      • If the value of start is positive, then store the required sum S as prefMatrix[i][end] – prefMatrix[i][start – 1].
      • Otherwise, update S as prefMatrix[i][end].
    • Insert S in an array arr[].
    • After iterating all rows in the submatrix, perform Kadane’s algorithm on the array A[] and update the maximum sum maxSum as the maximum of maxSum and value obtained by performing the Kadane’s Algorithm in this step.
  • After completing the above steps, print the value of maxSum as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to find maximum continuous
// maximum sum in the array
int kadane(vector<int> v)
{
    
    // Stores current and maximum sum
    int currSum = 0;
    int maxSum = INT_MIN;
  
    // Traverse the array v
    for (int i = 0;
         i < (int)v.size(); i++) {
  
        // Add the value of the
        // current element
        currSum += v[i];
  
        // Update the maximum sum
        if (currSum > maxSum) {
            maxSum = currSum;
        }
  
        if (currSum < 0) {
            currSum = 0;
        }
    }
  
    // Return the maximum sum
    return maxSum;
}
  
// Function to find the maximum
// submatrix sum
void maxSubmatrixSum(
    vector<vector<int> > A)
{
    
    // Store the rows and columns
    // of the matrix
    int r = A.size();
    int c = A[0].size();
  
    // Create an auxiliary matrix
    int** prefix = new int*[r];
  
    // Traverse the matrix, prefix
    // and initialize it will all 0s
    for (int i = 0; i < r; i++) {
  
        prefix[i] = new int;
        for (int j = 0; j < c; j++) {
            prefix[i][j] = 0;
        }
    }
  
    // Calculate prefix sum of all
    // rows of matrix A[][] and
    // store in matrix prefix[]
    for (int i = 0; i < r; i++) {
  
        for (int j = 0; j < c; j++) {
  
            // Update the prefix[][]
            if (j == 0)
                prefix[i][j] = A[i][j];
            else
                prefix[i][j] = A[i][j]
                               + prefix[i][j - 1];
        }
    }
  
    // Store the maximum submatrix sum
    int maxSum = INT_MIN;
  
    // Iterate for starting column
    for (int i = 0; i < c; i++) {
  
        // Iterate for last column
        for (int j = i; j < c; j++) {
  
            // To store current array
            // elements
            vector<int> v;
  
            // Traverse every row
            for (int k = 0; k < r; k++) {
  
                // Store the sum of the
                // kth row
                int el = 0;
  
                // Update the prefix
                // sum
                if (i == 0)
                    el = prefix[k][j];
                else
                    el = prefix[k][j]
                         - prefix[k][i - 1];
  
                // Push it in a vector
                v.push_back(el);
            }
  
            // Update the maximum
            // overall sum
            maxSum = max(maxSum, kadane(v));
        }
    }
  
    // Print the answer
    cout << maxSum << "\n";
}
  
// Driver Code
int main()
{
    vector<vector<int> > matrix = { { 0, -2, -7, 0 },
                                    { 9, 2, -6, 2 },
                                    { -4, 1, -4, 1 },
                                    { -1, 8, 0, -2 } };
  
    // Function Call
    maxSubmatrixSum(matrix);
  
    return 0;
}


Java




// Java program for the above approach
import java.util.*;
class GFG{
  
  // Function to find maximum continuous
  // maximum sum in the array
  static int kadane(Vector<Integer> v)
  {
  
    // Stores current and maximum sum
    int currSum = 0;
    int maxSum = Integer.MIN_VALUE;
  
    // Traverse the array v
    for (int i = 0;
         i < (int)v.size(); i++) 
    {
  
      // Add the value of the
      // current element
      currSum += v.get(i);
  
      // Update the maximum sum
      if (currSum > maxSum)
      {
        maxSum = currSum;
      }
  
      if (currSum < 0
      {
        currSum = 0;
      }
    }
  
    // Return the maximum sum
    return maxSum;
  }
  
  // Function to find the maximum
  // submatrix sum
  static void maxSubmatrixSum(int [][]A)
  {
    // Store the rows and columns
    // of the matrix
    int r = A.length;
    int c = A[0].length;
  
    // Create an auxiliary matrix
    int [][]prefix = new int[r][];
  
    // Traverse the matrix, prefix
    // and initialize it will all 0s
    for (int i = 0; i < r; i++) {
  
      prefix[i] = new int;
      for (int j = 0; j < c; j++) {
        prefix[i][j] = 0;
      }
    }
  
    // Calculate prefix sum of all
    // rows of matrix A[][] and
    // store in matrix prefix[]
    for (int i = 0; i < r; i++) {
  
      for (int j = 0; j < c; j++) {
  
        // Update the prefix[][]
        if (j == 0)
          prefix[i][j] = A[i][j];
        else
          prefix[i][j] = A[i][j]
          + prefix[i][j - 1];
      }
    }
  
    // Store the maximum submatrix sum
    int maxSum = Integer.MIN_VALUE;
  
    // Iterate for starting column
    for (int i = 0; i < c; i++) {
  
      // Iterate for last column
      for (int j = i; j < c; j++) {
  
        // To store current array
        // elements
        Vector<Integer> v = new Vector<Integer>();
  
        // Traverse every row
        for (int k = 0; k < r; k++) {
  
          // Store the sum of the
          // kth row
          int el = 0;
  
          // Update the prefix
          // sum
          if (i == 0)
            el = prefix[k][j];
          else
            el = prefix[k][j]
            - prefix[k][i - 1];
  
          // Push it in a vector
          v.add(el);
        }
  
        // Update the maximum
        // overall sum
        maxSum = Math.max(maxSum, kadane(v));
      }
    }
  
    // Print the answer
    System.out.print(maxSum+ "\n");
  }
  
  // Driver Code
  public static void main(String[] args)
  {
    int [][]matrix = { { 0, -2, -7, 0 },
                      { 9, 2, -6, 2 },
                      { -4, 1, -4, 1 },
                      { -1, 8, 0, -2 } };
  
    // Function Call
    maxSubmatrixSum(matrix);
  }
}
  
// This code is contributed by 29AjayKumar


Python3




# Python3 program for the above approach
import sys
  
# Function to find maximum continuous
# maximum sum in the array
def kadane(v):
      
    # Stores current and maximum sum
    currSum = 0
      
    maxSum = -sys.maxsize - 1
      
    # Traverse the array v
    for i in range(len(v)):
          
        # Add the value of the
        # current element
        currSum += v[i]
          
        # Update the maximum sum
        if (currSum > maxSum):
            maxSum = currSum
        if (currSum < 0):
            currSum = 0
      
    # Return the maximum sum
    return maxSum
  
# Function to find the maximum
# submatrix sum
def maxSubmatrixSum(A):
      
    # Store the rows and columns
    # of the matrix
    r = len(A)
    c = len(A[0])
      
    # Create an auxiliary matrix
    # Traverse the matrix, prefix
    # and initialize it will all 0s
    prefix = [[0 for i in range(c)] 
                 for j in range(r)]
      
    # Calculate prefix sum of all
    # rows of matrix A[][] and
    # store in matrix prefix[]
    for i in range(r):
        for j in range(c):
              
            # Update the prefix[][]
            if (j == 0):
                prefix[i][j] = A[i][j]
            else:
                prefix[i][j] = A[i][j] + prefix[i][j - 1]
      
    # Store the maximum submatrix sum
    maxSum = -sys.maxsize - 1
      
    #  Iterate for starting column
    for i in range(c):
          
        # Iterate for last column
        for j in range(i, c):
              
            # To store current array
            # elements
            v = []
              
            # Traverse every row
            for k in range(r):
                  
                # Store the sum of the
                # kth row
                el = 0
                  
                # Update the prefix
                # sum
                if (i == 0):
                    el = prefix[k][j]
                else:
                    el = prefix[k][j] - prefix[k][i - 1]
                  
                # Push it in a vector
                v.append(el)
              
            # Update the maximum
            # overall sum
            maxSum = max(maxSum, kadane(v))
      
    # Print the answer
    print(maxSum)
  
# Driver Code
matrix = [ [ 0, -2, -7, 0 ],
           [ 9, 2, -6, 2 ],
           [ -4, 1, -4, 1 ],
           [ -1, 8, 0, -2 ] ]
             
# Function Call
maxSubmatrixSum(matrix)
  
# This code is contributed by rag2127


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
  
public class GFG{
  
  // Function to find maximum continuous
  // maximum sum in the array
  static int kadane(List<int> v)
  {
  
    // Stores current and maximum sum
    int currSum = 0;
    int maxSum = int.MinValue;
  
    // Traverse the array v
    for (int i = 0;
         i < (int)v.Count; i++) 
    {
  
      // Add the value of the
      // current element
      currSum += v[i];
  
      // Update the maximum sum
      if (currSum > maxSum)
      {
        maxSum = currSum;
      }
  
      if (currSum < 0) 
      {
        currSum = 0;
      }
    }
  
    // Return the maximum sum
    return maxSum;
  }
  
  // Function to find the maximum
  // submatrix sum
  static void maxSubmatrixSum(int [,]A)
  {
    // Store the rows and columns
    // of the matrix
    int r = A.GetLength(0);
    int c = A.GetLength(1);
  
    // Create an auxiliary matrix
    int [,]prefix = new int[r,c];
  
    // Traverse the matrix, prefix
    // and initialize it will all 0s
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        prefix[i,j] = 0;
      }
    }
  
    // Calculate prefix sum of all
    // rows of matrix [,]A and
    // store in matrix prefix[]
    for (int i = 0; i < r; i++) {
  
      for (int j = 0; j < c; j++) {
  
        // Update the prefix[,]
        if (j == 0)
          prefix[i,j] = A[i,j];
        else
          prefix[i,j] = A[i,j]
          + prefix[i,j - 1];
      }
    }
  
    // Store the maximum submatrix sum
    int maxSum = int.MinValue;
  
    // Iterate for starting column
    for (int i = 0; i < c; i++) {
  
      // Iterate for last column
      for (int j = i; j < c; j++) {
  
        // To store current array
        // elements
        List<int> v = new List<int>();
  
        // Traverse every row
        for (int k = 0; k < r; k++) {
  
          // Store the sum of the
          // kth row
          int el = 0;
  
          // Update the prefix
          // sum
          if (i == 0)
            el = prefix[k,j];
          else
            el = prefix[k,j]
            - prefix[k,i - 1];
  
          // Push it in a vector
          v.Add(el);
        }
  
        // Update the maximum
        // overall sum
        maxSum = Math.Max(maxSum, kadane(v));
      }
    }
  
    // Print the answer
    Console.Write(maxSum+ "\n");
  }
  
  // Driver Code
  public static void Main(String[] args)
  {
    int [,]matrix = { { 0, -2, -7, 0 },
                      { 9, 2, -6, 2 },
                      { -4, 1, -4, 1 },
                      { -1, 8, 0, -2 } };
  
    // Function Call
    maxSubmatrixSum(matrix);
  }
}
  
// This code is contributed by 29AjayKumar


Javascript




<script>
// Javascript program for the above approach
  
// Function to find maximum continuous
// maximum sum in the array    
function kadane(v)
{
    // Stores current and maximum sum
    let currSum = 0;
    let maxSum = Number.MIN_VALUE;
   
    // Traverse the array v
    for (let i = 0;
         i < v.length; i++)
    {
   
      // Add the value of the
      // current element
      currSum += v[i];
   
      // Update the maximum sum
      if (currSum > maxSum)
      {
        maxSum = currSum;
      }
   
      if (currSum < 0)
      {
        currSum = 0;
      }
    }
   
    // Return the maximum sum
    return maxSum;
}
  
// Function to find the maximum
// submatrix sum
function maxSubmatrixSum(A)
{
    // Store the rows and columns
    // of the matrix
    let r = A.length;
    let c = A[0].length;
   
    // Create an auxiliary matrix
    let prefix = new Array(r);
   
    // Traverse the matrix, prefix
    // and initialize it will all 0s
    for (let i = 0; i < r; i++) {
   
      prefix[i] = new Array(c);
      for (let j = 0; j < c; j++) {
        prefix[i][j] = 0;
      }
    }
   
    // Calculate prefix sum of all
    // rows of matrix A[][] and
    // store in matrix prefix[]
    for (let i = 0; i < r; i++) {
   
      for (let j = 0; j < c; j++) {
   
        // Update the prefix[][]
        if (j == 0)
          prefix[i][j] = A[i][j];
        else
          prefix[i][j] = A[i][j]
          + prefix[i][j - 1];
      }
    }
   
    // Store the maximum submatrix sum
    let maxSum = Number.MIN_VALUE;
   
    // Iterate for starting column
    for (let i = 0; i < c; i++) {
   
      // Iterate for last column
      for (let j = i; j < c; j++) {
   
        // To store current array
        // elements
        let v = [];
   
        // Traverse every row
        for (let k = 0; k < r; k++) {
   
          // Store the sum of the
          // kth row
          let el = 0;
   
          // Update the prefix
          // sum
          if (i == 0)
            el = prefix[k][j];
          else
            el = prefix[k][j]
            - prefix[k][i - 1];
   
          // Push it in a vector
          v.push(el);
        }
   
        // Update the maximum
        // overall sum
        maxSum = Math.max(maxSum, kadane(v));
      }
    }
   
    // Print the answer
    document.write(maxSum+ "<br>");
}
  
// Driver Code
let matrix=[[ 0, -2, -7, 0 ],
                      [ 9, 2, -6, 2 ],
                      [ -4, 1, -4, 1 ],
                      [ -1, 8, 0, -2 ]];
// Function Call
maxSubmatrixSum(matrix);
  
// This code is contributed by unknown2108
</script>


Output: 

15

 

Time Complexity: O(N3)
Auxiliary Space: O(N2)

Related Topic: Subarrays, Subsequences, and Subsets in Array



Last Updated : 11 Jul, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads