Given an n x n
matrix of positive
and negative
integers, find the submatrix with the largest possible sum.
Example
Example1
Input:
matrix = [
[1,3,-1],
[2,3,-2],
[-1,-2,-3]
]
Output: 9
Explanation:
the submatrix with the largest possible sum is:
[
[1,3],
[2,3]
]
Example2
Input:
matrix = [
[1,1,1],
[1,1,1],
[1,1,1]
]
Output: 9
Explanation:
the submatrix with the largest possible sum is:
[
[1,1,1],
[1,1,1],
[1,1,1]
]
思路:暴力解:O^4, dp[i][j] 表示以i,j为最右下角,起点为0,0的矩阵sum。会time out。
public class Solution {
/**
* @param matrix: the given matrix
* @return: the largest possible sum
*/
public int maxSubmatrix(int[][] matrix) {
if(matrix == null || matrix.length == 0) {
return 0;
}
int m = matrix.length;
int n = matrix[0].length;
int[][] dp = new int[m][n];
for(int i = 0; i < m; i ++) {
for(int j = 0; j < n; j++) {
dp[i][j] = calculatedp(matrix, i, j);
}
}
int globalmax = 0;
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
for(int p = i ; p < m; p++) {
for(int q = j ; q < n; q++) {
int dpA = calculatedp(matrix, i, j);
int dpB = calculatedp(matrix, i, q);
int dpC = calculatedp(matrix, p, j);
int dpD = calculatedp(matrix, p, q);
int area = dpD - dpB - dpC + dpA +
line(matrix, i,j, i, q) + line(matrix, i, j, p, j) - matrix[i][j];
globalmax = Math.max(globalmax, dpA);
globalmax = Math.max(globalmax, dpB);
globalmax = Math.max(globalmax, dpC);
globalmax = Math.max(globalmax, dpD);
globalmax = Math.max(globalmax, area);
}
}
}
}
return globalmax;
}
private int line(int[][] matrix, int x1, int y1, int x2, int y2) {
int sum = 0;
for(int i = x1; i <= x2; i ++) {
for(int j = y1; j <= y2; j++) {
sum += matrix[i][j];
}
}
return sum;
}
private int calculatedp(int[][] matrix, int x, int y) {
int sum = 0;
for(int i = 0; i <= x; i++) {
for(int j = 0; j <= y; j++) {
sum += matrix[i][j];
}
}
return sum;
}
}
牛逼的 是这个:dp[i][j]表示的是以i,j为底的colum sum。这样把一片计算规划成一个col的计算,然后就把二维降低为一维,问题转换为,求maximum subarray 的计算了。
首先求得每列的sum[i][j]
然后设置两条行线 l 和 h
在设置一条纵线k, 从左到右让k 切割l h之间的矩阵,每次把l h k 和 k-1之间的矩阵看成一个元素
此时可以把这道题降维考虑,类似于最大子数组和,找到连续的l,h之间矩阵的连续最大和的情况
最终复杂度是n^3
public class Solution {
/**
* @param matrix: the given matrix
* @return: the largest possible sum
*/
public int maxSubmatrix(int[][] matrix) {
if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return 0;
int m = matrix.length;
int n = matrix[0].length;
// col sum, 将二维降为一维;
int[][] sum =new int[m+1][n+1];
// sum[i][j] 表示以i,j为底的一列的sum;
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
sum[i][j] = sum[i-1][j] + matrix[i-1][j-1];
}
}
int maxsum = Integer.MIN_VALUE;
for(int i = 0; i <= m; i++) {
for(int j = i + 1; j <= m; j++) {
int cur = 0;
for(int k = 1; k <= n; k++) {
cur += sum[j][k] - sum[i][k];
maxsum = Math.max(maxsum, cur);
if(cur < 0) {
cur = 0;
}
}
}
}
return maxsum;
}
}