题目描述:
LeetCode 363. Max Sum of Rectangle No Larger Than K
Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix such that its sum is no larger than k.
Example:
Given matrix = [ [1, 0, 1], [0, -2, 3] ] k = 2
The answer is 2
. Because the sum of rectangle [[0, 1], [-2, 3]]
is 2 and 2 is the max number no larger than k (k = 2).
Note:
- The rectangle inside the matrix must have an area > 0.
- What if the number of rows is much larger than the number of columns?
题目大意:
给定一个非空的二维矩阵matrix与一个整数k,在矩阵内部寻找和不大于k的最大矩形和。
测试用例如题目描述。
注意:
- 矩阵内部的矩形面积必须 > 0。
- 如果矩阵的行数远大于列数时,算法应当怎样调整?
解题思路:
题目可以通过降维转化为求解子问题:和不大于k的最大子数组,解法参考:https://www.quora.com/Given-an-array-of-integers-A-and-an-integer-k-find-a-subarray-that-contains-the-largest-sum-subject-to-a-constraint-that-the-sum-is-less-than-k
首先枚举列的起止范围x, y
,子矩阵matrix[][x..y]
可以通过部分和数组sums
进行表示:
sums[i] = Σ(matrix[i][x..y])
接下来求解sums数组中和不大于k的最大子数组的和。
如果矩阵的列数远大于行数,则将枚举列变更为枚举行即可。
Java代码:
public class Solution {
public int maxSumSubmatrix(int[][] matrix, int k) {
int m = matrix.length, n = 0;
if (m > 0) n = matrix[0].length;
if (m * n == 0) return 0;
int M = Math.max(m, n);
int N = Math.min(m, n);
int ans = Integer.MIN_VALUE;
for (int x = 0; x < N; x++) {
int sums[] = new int[M];
for (int y = x; y < N; y++) {
TreeSet<Integer> set = new TreeSet<Integer>();
int num = 0;
for (int z = 0; z < M; z++) {
sums[z] += m > n ? matrix[z][y] : matrix[y][z];
num += sums[z];
if (num <= k) ans = Math.max(ans, num);
Integer i = set.ceiling(num - k);
if (i != null) ans = Math.max(ans, num - i);
set.add(num);
}
}
}
return ans;
}
}
同样思路实现的Python代码:
class Solution(object):
def maxSumSubmatrix(self, matrix, k):
"""
:type matrix: List[List[int]]
:type k: int
:rtype: int
"""
m = len(matrix)
n = len(matrix[0]) if m else 0
M = max(m, n)
N = min(m, n)
ans = None
for x in range(N):
sums = [0] * M
for y in range(x, N):
slist, num = [], 0
for z in range(M):
sums[z] += matrix[z][y] if m > n else matrix[y][z]
num += sums[z]
if num <= k: ans = max(ans, num)
i = bisect.bisect_left(slist, num - k)
if i != len(slist): ans = max(ans, num - slist[i])
bisect.insort(slist, num)
return ans or 0
另请参阅LeetCode Discuss:https://leetcode.com/discuss/109749/accepted-c-codes-with-explanation-and-references
本文链接:http://bookshadow.com/weblog/2016/06/22/leetcode-max-sum-of-sub-matrix-no-larger-than-k/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。