Given a 2D array, find the minimum sum submatrix in it.
Examples:
Input : M[][] = {{1, 2, -1, -4, -20},
{-8, -3, 4, 2, 1},
{3, 8, 10, 1, 3},
{-4, -1, 1, 7, -6}}
Output : -26
Submatrix starting from (Top, Left): (0, 0)
and ending at (Bottom, Right): (1, 4) indexes.
The elements are of the submatrix are:
{ {1, 2, -1, -4, -20},
{-8, -3, 4, 2, 1} } having sum = -26
Method 1 (Naive Approach): Check every possible submatrix in a given 2D array. This solution requires 4 nested loops and the time complexity of this solution would be O(n^4).
Method 2 (Efficient Approach):
Kadane’s algorithm for the 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 minimum sum contiguous rows for every left and right column pair. We basically find top and bottom row numbers (which have minimum 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 the sum of elements from left to right in row i.
If we apply Kadane’s 1D algorithm on temp[] and get the minimum sum subarray of temp, this minimum sum would be the minimum possible sum with left and right as boundary columns. To get the overall minimum sum, we compare this sum with the minimum 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, minSum = INT_MAX, 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 < minSum) {
minSum = sum;
*start = local_start;
*finish = i;
}
}
if (*finish != -1)
return minSum;
minSum = arr[0];
*start = *finish = 0;
for (i = 1; i < n; i++) {
if (arr[i] < minSum) {
minSum = arr[i];
*start = *finish = i;
}
}
return minSum;
}
void findMinSumSubmatrix( int M[][COL])
{
int minSum = INT_MAX, 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 < minSum) {
minSum = sum;
finalLeft = left;
finalRight = right;
finalTop = start;
finalBottom = finish;
}
}
}
cout << "(Top, Left): (" << finalTop << ", "
<< finalLeft << ")\n" ;
cout << "(Bottom, Right): (" << finalBottom << ", "
<< finalRight << ")\n" ;
cout << "Minimum sum: " << minSum;
}
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 } };
findMinSumSubmatrix(M);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG
{
static int ROW = 4 ;
static int COL = 5 ;
static int start;
static int finish;
static int kadane( int [] arr, int n)
{
int sum = 0 , minSum = Integer.MAX_VALUE, 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 < minSum)
{
minSum = sum;
start = local_start;
finish = i;
}
}
if (finish != - 1 )
return minSum;
minSum = arr[ 0 ];
start = finish = 0 ;
for (i = 1 ; i < n; i++)
{
if (arr[i] < minSum)
{
minSum = arr[i];
start = finish = i;
}
}
return minSum;
}
static void findMinSumSubmatrix( int [][] M)
{
int minSum = Integer.MAX_VALUE;
int finalLeft = 0 , finalRight = 0 , finalTop = 0 , finalBottom = 0 ;
int left, right, i;
int []temp= new int [ROW];
int sum;
for (left = 0 ; left < COL; ++left)
{
Arrays.fill(temp, 0 );
for (right = left; right < COL; ++right)
{
for (i = 0 ; i < ROW; ++i)
temp[i] += M[i][right];
sum = kadane(temp, ROW);
if (sum < minSum)
{
minSum = sum;
finalLeft = left;
finalRight = right;
finalTop = start;
finalBottom = finish;
}
}
}
System.out.println( "(Top, Left): (" +
finalTop + ", " +
finalLeft + ")" );
System.out.println( "(Bottom, Right): (" +
finalBottom + ", " +
finalRight + ")" );
System.out.println( "Minimum sum: " + minSum);
}
public static void main (String[] args)
{
int [][] M ={{ 1 , 2 , - 1 , - 4 , - 20 },
{ - 8 , - 3 , 4 , 2 , 1 },
{ 3 , 8 , 10 , 1 , 3 },
{ - 4 , - 1 , 1 , 7 , - 6 }};
findMinSumSubmatrix(M);
}
}
|
Python3
import sys
def kadane(arr, start, finish, n):
sum , minSum = 0 , sys.maxsize
finish = - 1
local_start = 0
for i in range (n):
sum + = arr[i]
if ( sum > 0 ):
sum = 0
local_start = i + 1
elif ( sum < minSum):
minSum = sum
start = local_start
finish = i
if (finish ! = - 1 ):
return minSum, start, finish
minSum = arr[ 0 ]
start, finish = 0 , 0
for i in range ( 1 , n):
if (arr[i] < minSum):
minSum = arr[i]
start = finish = i
return minSum, start, finish
def findMinSumSubmatrix(M):
minSum = sys.maxsize
finalLeft = 0
finalRight = 0
finalTop = 0
finalBottom = 0
sum , start, finish = 0 , 0 , 0
for left in range ( 5 ):
temp = [ 0 for i in range ( 5 )]
for right in range (left, 5 ):
for i in range ( 4 ):
temp[i] + = M[i][right]
sum , start, finish = kadane(temp, start,
finish, 4 )
if ( sum < minSum):
minSum = sum
finalLeft = left
finalRight = right
finalTop = start
finalBottom = finish
print ( "(Top, Left): (" , finalTop,
"," , finalLeft, ")" )
print ( "(Bottom, Right): (" , finalBottom,
"," , finalRight, ")" )
print ( "Minimum sum:" , minSum)
if __name__ = = '__main__' :
M = [ [ 1 , 2 , - 1 , - 4 , - 20 ],
[ - 8 , - 3 , 4 , 2 , 1 ],
[ 3 , 8 , 10 , 1 , 3 ],
[ - 4 , - 1 , 1 , 7 , - 6 ] ]
findMinSumSubmatrix(M)
|
C#
using System;
public class GFG
{
static int ROW = 4;
static int COL = 5;
static int start;
static int finish;
static int kadane( int [] arr, int n)
{
int sum = 0, minSum = Int32.MaxValue, 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 < minSum)
{
minSum = sum;
start = local_start;
finish = i;
}
}
if (finish != -1)
return minSum;
minSum = arr[0];
start = finish = 0;
for (i = 1; i < n; i++)
{
if (arr[i] < minSum)
{
minSum = arr[i];
start = finish = i;
}
}
return minSum;
}
static void findMinSumSubmatrix( int [,] M)
{
int minSum = Int32.MaxValue;
int finalLeft = 0 , finalRight = 0, finalTop = 0, finalBottom = 0;
int left, right, i;
int []temp= new int [ROW];
int sum;
for (left = 0; left < COL; ++left)
{
Array.Fill(temp, 0);
for (right = left; right < COL; ++right)
{
for (i = 0; i < ROW; ++i)
temp[i] += M[i, right];
sum = kadane(temp, ROW);
if (sum < minSum)
{
minSum = sum;
finalLeft = left;
finalRight = right;
finalTop = start;
finalBottom = finish;
}
}
}
Console.WriteLine( "(Top, Left): (" +
finalTop + ", " +
finalLeft + ")" );
Console.WriteLine( "(Bottom, Right): (" +
finalBottom + ", " +
finalRight + ")" );
Console.WriteLine( "Minimum sum: " + minSum);
}
static public void Main ()
{
int [,] M ={{ 1, 2, -1, -4, -20 },
{ -8, -3, 4, 2, 1 },
{ 3, 8, 10, 1, 3 },
{ -4, -1, 1, 7, -6 }};
findMinSumSubmatrix(M);
}
}
|
Javascript
<script>
var ROW = 4;
var COL = 5;
var start;
var finish;
function kadane(arr , n) {
var sum = 0, minSum = Number.MAX_VALUE, 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 < minSum) {
minSum = sum;
start = local_start;
finish = i;
}
}
if (finish != -1)
return minSum;
minSum = arr[0];
start = finish = 0;
for (i = 1; i < n; i++) {
if (arr[i] < minSum) {
minSum = arr[i];
start = finish = i;
}
}
return minSum;
}
function findMinSumSubmatrix(M)
{
var minSum = Number.MAX_VALUE;
var finalLeft = 0, finalRight = 0, finalTop = 0,
finalBottom = 0;
var left, right, i;
var temp = Array(ROW).fill(0);
var sum;
for (left = 0; left < COL; ++left) {
temp.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 < minSum) {
minSum = 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( "Minimum sum: " + minSum);
}
var M = [ [ 1, 2, -1, -4, -20 ],
[ -8, -3, 4, 2, 1 ],
[ 3, 8, 10, 1, 3 ],
[ -4, -1, 1, 7, -6 ] ];
findMinSumSubmatrix(M);
</script>
|
Output(Top, Left): (0, 0)
(Bottom, Right): (1, 4)
Minimum sum: -26
Time Complexity: O(n3)
Auxiliary Space: O(ROW)
This article is contributed by Ayush Jauhari. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.