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?
思路:先考虑一维数组的最大Rectangle,因为有负数,所以O(N)的背包算法不行,brute force是O(N^2),那我们可以可以把一维数组的这个问题用O(N*logN)的复杂度解决呢?答案是可以的,
遍历一遍,running sum,遍历到i位置时,最需要的是:sum[i]-target出现在之前的sum[0...i]中,但不一定找得到,所以我们只能找比它小一点的,但是是最大的那个数,这就决定了我们要用的数据结构,不是用HashTable,,而是Tree
/*
* 因为要找的数可能并不在数组里,只能找比它小的最大的数
* 这也决定了我们要用的数据结构不是HashTable,而是Tree
*/
public class oneDTest {
public static void main(String[] args) {
int[] a = new int[]{2,2,-1};
System.out.println(MostNoLargerThan(a, 0));
}
// since there could be negative number, packet algorithm will not work
// but we can do it in NlogN using a tree
private static int MostNoLargerThan(int[] a, int target) {
TreeSet<Integer> set = new TreeSet<Integer>();
int sum = 0;
set.add(sum);
int ret = Integer.MIN_VALUE;
for(int i : a) {
sum += i;
Integer ceiling = set.ceiling(sum-target);
if(ceiling != null) ret = Math.max(ret, sum-ceiling);
set.add(sum);
}
return ret;
}
}
有了一维数组,二维数组无非就是把二维转换成一维罢了
public class Solution {
public int maxSumSubmatrix(int[][] matrix, int k) {
int max = Integer.MIN_VALUE;
// 先确定横着的2刀切的位置
for(int i=0; i<matrix.length; i++) {
int[] sum = new int[matrix[0].length];
for(int j=i; j<matrix.length; j++) {
for(int q=0; q<matrix[0].length; q++)
sum[q] += matrix[j][q];
max = Math.max(max, MostNoLargerThan(sum, k));
}
}
return max;
}
private static int MostNoLargerThan(int[] a, int target) {
TreeSet<Integer> set = new TreeSet<Integer>();
int sum = 0;
set.add(sum);
int ret = Integer.MIN_VALUE;
for(int i : a) {
sum += i;
Integer ceiling = set.ceiling(sum-target);
if(ceiling != null) ret = Math.max(ret, sum-ceiling);
set.add(sum);
}
return ret;
}
}
其实最开始的时候,想用二分来着,因为好多求min(max)的问题就是用二分逼近答案的,但是这个题貌似没有明显的min(max),max(min)的意思