363. 矩形区域不超过 K 的最大数值和
给你一个 m x n
的矩阵 matrix
和一个整数 k
,找出并返回矩阵内部矩形区域的不超过 k
的最大数值和。
题目数据保证总会存在一个数值和不超过 k
的矩形区域。
示例 1:
输入:matrix = [[1,0,1],[0,-2,3]], k = 2
输出:2
解释:蓝色边框圈出来的矩形区域 [[0, 1], [-2, 3]] 的数值和是 2,且 2 是不超过 k 的最大数字(k = 2)。
示例 2:
输入:matrix = [[2,2,-1]], k = 3
输出:3
提示:
- m == matrix.length
- n == matrix[i].length
- 1 <= m, n <= 100
- -100 <= matrix[i][j] <= 100
- -105 <= k <= 105
方法一:前缀和暴力求解
加班严重,先写个暴力解法~。
关于二维数组的前缀和,有两点需要弄懂:
- 二维数组的前缀和怎么表示:
preSum[i][j]
表示从[0][0]
到[i][j]
的矩阵之和。 - 在前缀和基础上如何以O(1)时间复杂度求任意矩阵之和:如下图,求黄色区域的矩阵之和。
只要用preSum[p][q]
-上方preSum[i - 1][q]
-左边preSum[i][j - 1]
+多减去的部分preSum[i - 1][j - 1]
。
枚举所有矩阵,找出小于等于 k 的最大值即可。
参考代码
public int maxSumSubmatrix(int[][] matrix, int k) {
int m = matrix.length, n = matrix[0].length;
int[][] preSum = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
preSum[i][j] = preSum[i][j - 1] + preSum[i - 1][j] - preSum[i - 1][j - 1] + matrix[i - 1][j - 1];
}
}
int ret = -200000;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
for (int p = i; p <= m; p++) {
for (int q = j; q <= n; q++) {
int sum = preSum[p][q] - preSum[p][j - 1] - preSum[i - 1][q] + preSum[i - 1][j - 1];
if (k >= sum && sum > ret) {
ret = sum;
}
}
}
}
}
return ret;
}
执行结果