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?
转化成前缀和归并排序+双指针查找前缀和之差接近k的数,或者前缀和+BST查找前缀和之差接近k的数。
时间复杂度O(n^3logn).
前缀和+归并排序+双指针.
class Solution {
public int maxSumSubmatrix(int[][] m, int k) {
int max=Integer.MIN_VALUE;
for(int i=0;i<m[0].length;i++){
int[] arr=new int[m.length];
for(int j=i;j<m[0].length;j++){
for(int n=0;n<m.length;n++){
arr[n]+=m[n][j];
}
int[] sum=new int[m.length];
for(int n=0;n<m.length;n++){
if(n==0) sum[0]=arr[0];
else sum[n]=arr[n]+sum[n-1];
}
max=Math.max(max,find(sum,k,0,sum.length-1));
}
}
return max;
}
int find(int[] sum,int k,int l,int r){
if(l>r) return Integer.MIN_VALUE;
if(l==r){
if(sum[l]<=k) return sum[l];
return Integer.MIN_VALUE;
}
int m=(l+r)/2;
int c1=find(sum,k,l,m);
int c2=find(sum,k,m+1,r);
for(int i=l,j=m+1;i<=m&&j<=r;){//双指针
if(sum[j]-sum[i]<=k){
c1=Math.max(c1,sum[j]-sum[i]);
j++;
}else{
i++;
}
}
//归并
int[] a1=new int[m-l+1];
int[] a2=new int[r-m];
for(int i=l;i<=m;i++) a1[i-l]=sum[i];
for(int i=m+1;i<=r;i++) a2[i-m-1]=sum[i];
for(int i=l,j=0,n=0;i<=r;i++){
if(n>=a2.length||(j<a1.length&&a1[j]<a2[n])){
sum[i]=a1[j++];
}else{
sum[i]=a2[n++];
}
}
return Math.max(c1,c2);
}
}
前缀和+BST(用到了jdk中的BST)
class Solution {
public int maxSumSubmatrix(int[][] m, int k) {
int max=Integer.MIN_VALUE;
for(int i=0;i<m[0].length;i++){
int[] arr=new int[m.length];
for(int j=i;j<m[0].length;j++){
for(int n=0;n<m.length;n++){
arr[n]+=m[n][j];
}
int[] sum=new int[m.length];
TreeSet<Integer> tree=new TreeSet<>();
tree.add(0);
for(int n=0;n<m.length;n++){
if(n==0) sum[0]=arr[0];
else sum[n]=arr[n]+sum[n-1];
Integer t=tree.ceiling(sum[n]-k);
if(t!=null){
max=Math.max(max,sum[n]-t);
}
tree.add(sum[n]);
}
}
}
return max;
}
}