363. Max Sum of Rectangle No Larger Than K

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Solution {
public int maxSumSubmatrix(int[][] matrix, int k) {
int m = matrix.length, n = matrix[0].length;

int[][] sumMatrix = new int[m + 1][n + 1]; // 多申请一个是避免处理索引越界的情况

for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
sumMatrix[i][j] = sumMatrix[i - 1][j] + sumMatrix[i][j - 1] - sumMatrix[i - 1][j - 1] + matrix[i - 1][j - 1];
}
}

int maxSum = Integer.MIN_VALUE;

// 统一使用 sumMatrix 中的下标,即从 1 开始
for (int startRow = 1; startRow <= m; startRow++) {
for (int endRow = startRow; endRow <= m; endRow++) {
// 使用 TreeSet 记录所有遍历过的右边界,注意声明为 TreeSet 类型以使用特有的 ceiling 方法
TreeSet<Integer> set = new TreeSet<>();
set.add(0); // 当左部分区域为空时,左部分区域和为 0

for (int endCol = 1; endCol <= n; endCol++) {
int leftmostToRightAreaSum = sumMatrix[endRow][endCol] - sumMatrix[startRow - 1][endCol]; // 最左侧至当前 encCol 的区域和
// ceiling 的含义为寻找大于等于 leftmostToRightAreaSum - k 的最小值
// 即:leftArea >= leftmostToRightAreaSum - k
// 即:k >= leftmostToRightAreaSum - leftArea
// 即:k >= rightArea
// 即:rightArea <= k,即题意要求的不超过 k 的最大数值和
// 即:leftArea 需要在满足条件时尽可能地小,以使右边区域尽可能地大
Integer leftAreaSum = set.ceiling(leftmostToRightAreaSum - k);
if (leftAreaSum != null) {
int rightAreaSum = leftmostToRightAreaSum - leftAreaSum;
maxSum = Math.max(maxSum, rightAreaSum);
}
set.add(leftmostToRightAreaSum);
}
}
}

return maxSum;
}
}

References

363. Max Sum of Rectangle No Larger Than K