题目
给定一个正整数、负整数和 0 组成的 N × M 矩阵,编写代码找出元素总和最大的子矩阵。
返回一个数组 [r1, c1, r2, c2],其中 r1, c1 分别代表子矩阵左上角的行号和列号,r2, c2 分别代表右下角的行号和列号。若有多个满足条件的子矩阵,返回任意一个均可。
注意:本题相对书上原题稍作改动
示例:
输入:
[
[-1,0],
[0,-1]
]
输出:[0,1,0,1]
解释:输入中标粗的元素即为输出所表示的矩阵
1
2
3
4
5
6
7
说明:
1 <= matrix.length, matrix[0].length <= 200
最大子序列和的二维化而已:
import java.util.Arrays;
class Solution {
public int[] getMaxMatrix(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int[] dp = new int[n];
int max = Integer.MIN_VALUE;
int[] result = new int[4];
// 枚举子矩阵上界
for (int i = 0; i < m; i++) {
// 每次更换上界,需要将 dp 重置为 0
Arrays.fill(arr, 0);
// 枚举子矩阵下界
for (int j = i; j < m; j++) {
// 从左到右,计算子矩阵上下界之间的列和,第 k 列放到 dp[k] 中
// 由于下界是逐行递增,每次只用把新增的一行累加到 dp 中即可
for (int k = 0; k < n; k++) {
arr[k] += matrix[j][k];
}
// 计算列和数组 dp 的最大子序列和
int[] lss = lss(arr);
if (lss[0] > max) {
max = lss[0];
result = new int[]{i, lss[1], j, lss[2]};
}
}
}
return result;
}
// 最大子数组和,返回最大值和边界
private int[] lss(int[] arr) {
int max = Integer.MIN_VALUE, sum = Integer.MIN_VALUE;
int[] result = new int[3];
int start = 0;
for (int i = 0; i < arr.length; i++) {
if (sum < 0) {
start = i;
sum = arr[i];
} else {
sum = sum + arr[i];
}
if (sum > max) {
result[0] = sum;
result[1] = start;
result[2] = i;
max = sum;
}
}
return result;
}
}