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:

  1. The rectangle inside the matrix must have an area > 0.

  1. 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)的意思

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值