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:
Input: matrix = [[1,0,1],[0,-2,3]], k = 2
Output: 2
Explanation: 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?
思路:find the max sum rectangle in 2D array https://www.youtube.com/watch?v=yCQN096CwWM
核心思想就是:每列column,从左向右投影,left, right, 是左右边界,然后sums[n] 是长度为row的投影sum,也就是prefixsum。每次移动left, right,计算出sums array之后,问题就转换为,在一个array里面,找subarray sum最接近K的sum;这里用了treeset ceiling是第一个大于input的value,num >= currsum - k; currsum - num <= k; 每次update这个currsum - num 就可以了。currsum 是累加的sum;
注意:currusm - num 代表的就是下面的block的matrix;set.add(0); // 需要padding,是为了解决只有一个row value的情况;比如说cursum = 10, k = 10,那么就只有一个sum的话,就是要返回10,如果没有0,就会返回null,得不到sum就等于k的情况;
class Solution {
public int maxSumSubmatrix(int[][] matrix, int k) {
if(matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int n = matrix.length;
int m = matrix[0].length;
int result = Integer.MIN_VALUE;
for(int left = 0; left < m; left++) {
int[] arr = new int[n];
for(int right = left; right < m; right++) {
for(int i = 0; i < n; i++) {
arr[i] += matrix[i][right];
}
TreeSet<Integer> treeset = new TreeSet<>();
// 需要padding,是为了解决只有一个row value的情况;
// 比如说cursum = 10, k = 10,那么就只有一个sum的话,就是要返回10,如果没有0,就会返回null,得不到sum就等于k的情况;
treeset.add(0);
int cursum = 0;
for(int prefixsum: arr) {
cursum += prefixsum;
// num >= cursum - k;
// k >= cursum - num;
Integer num = treeset.ceiling(cursum - k);
if(num != null) {
// k >= cursum - num;
// currusm - num 代表的就是下面的block的matrix;
result = Math.max(result, cursum - num);
}
treeset.add(cursum);
}
}
}
return result;
}
}