Given a matrix of both +ve and -ve numbers, find out the maximum sum sub matrix.
First of all we will calculate the sum matrix where s[i][j] = sum of all the elements from [0,0] to [i,j]
Given Matrix:
1 1 1
1 1 1
1 1 1
Maximum Sum : 9 (because all numbers are positive, we will output complete matrix)
Given Matrix:
-1 -2 -3 -4
-5 -6 -7 -8
-9 -10 -11 -12
-13 -14 -15 -16
Maximum Sum : 0 ( we take nothing, as all numbers are negative)
Given Matrix:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
Maximum Sum: 15
Output Matrix :
9 2
-4 1
-1 8
int s[ROW][COL];
void computeSumMatrix(int a[][COL], int r, int c) {
for (int i = 0; i < r; i++)
if (i == 0)
s[i][0] = a[i][0];
else
s[i][0] = s[i - 1][0] + a[i][0];
for (int j = 0; j < c; j++)
if (j == 0)
s[0][j] = a[0][j];
else
s[0][j] = s[0][j - 1] + a[0][j];
for (int i = 1; i < r; i++) {
for (int j = 1; j < c; j++) {
s[i][j] = a[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
}
}
}
Now we will write a method to get the sum of a sub matrix given upper-left (r1,c1) indexes and lower-bottom (r2,c2) indexes
int getSubmatSum(int r1, int c1, int r2, int c2) {
if (r1 == 0 && c1 == 0)
return s[r2][c2];
if (r1 == 0)
return s[r2][c2] - s[r2][c1 - 1];
if (c1 == 0)
return s[r2][c2] - s[r1 - 1][c2];
return s[r2][c2] - s[r1 - 1][c2] - s[r2][c1 - 1] + s[r1 - 1][c1 - 1];
}
Using both these methods, we can iterate through all the possible sub matrices and get their sum in O(1). To iterate though all the possible sub-matrices would take O(n^4).
int getMaxSubmatSum(int a[][COL], int r, int c) {
int maxsum = 0;
for (int r1 = 0; r1 < r; r1++) {
for (int c1 = 0; c1 < c; c1++) {
for (int r2 = r1; r2 < r; r2++) {
for (int c2 = c1; c2 < c; c2++) {
int sum = getSubmatSum(r1, c1, r2, c2);
maxsum = max(sum, maxsum);
}
}
}
}
return maxsum;
}
Now, we are going to optimize this solution to O(n^3). The trick is to apply Kadane's algorithm on a 2D matrix.
We will consider all the possible 2D matrices which are starting from 0th column and treat them as 1D arrays.
int getMaxSubmatSum2(int a[][COL], int r, int c) {
int globalmax = 0;
for (int i = 0; i < r; i++)
for (int j = i; j < r; j++) {
int localmax = 0;
for (int k = 0; k < c; k++) {
localmax = max(localmax + getSubmatSum(i, k, j, k), 0);
globalmax = max(localmax, globalmax);
}
}
return globalmax;
}
Test Cases Given Matrix:
1 1 1
1 1 1
1 1 1
Maximum Sum : 9 (because all numbers are positive, we will output complete matrix)
Given Matrix:
-1 -2 -3 -4
-5 -6 -7 -8
-9 -10 -11 -12
-13 -14 -15 -16
Maximum Sum : 0 ( we take nothing, as all numbers are negative)
Given Matrix:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
Maximum Sum: 15
Output Matrix :
9 2
-4 1
-1 8
You can find the full source code of both these algorithms on my github page: Here
No comments:
Post a Comment