您的位置:首页 > 其它

Max Sum of Rectangle No Larger Than K

2016-07-17 21:51 337 查看
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?

思路

  使用l和r划定长方形的左右边界范围,然后在这个范围内,依次记录长方形的上界固定为第一行,下界从第一行到最后一行对应的长方形的和到数组sum。现在问题转换为寻找最合适的sum[j]-sum[i](j和i对应长方形的上下界),使得该值不大于k,但是最接近k。这个问题可以从Quora上找到解答:

  You can do this in O(nlog(n))

  First thing to note is that sum of subarray (i,j] is just the sum of the first j elements less the sum of the first i elements. Store these cumulative sums in the array cum. Then the problem reduces to finding i,j such that i<j and cum[j]−cum[i] is as close to k but lower than it.

  To solve this, scan from left to right. Put the cum[i] values that you have encountered till now into a set. When you are processing cum[j] what you need to retrieve from the set is the smallest number in the set such which is not smaller than cum[j]−k. This lookup can be done in O(log(n)) using lower_bound. Hence the overall complexity is O(nlog⁡(n)).

  Here is a c++ function that does the job, assuming that K>0 and that the empty interval with sum zero is a valid answer. The code can be tweaked easily to take care of more general cases and to return the interval itself.

  对应代码:

int best_cumulative_sum(int ar[],int N,int K)
{
set<int> cumset;
cumset.insert(0);
int best=0,cum=0;
for(int i=0;i<N;i++)
{
cum+=ar[i];
set<int>::iterator sit=cumset.lower_bound(cum-K);
if(sit!=cumset.end())best=max(best,cum-*sit);
cumset.insert(cum);
}
return best;
}


  在上述基础之上,我们稍加改变,就能够写出下述代码完成此题了。

class Solution {
public:
int maxSumSubmatrix(vector<vector<int>> &matrix, int k) {
int row = matrix.size();
if (row == 0)
return 0;
int col = matrix[0].size();
int ret = INT_MIN;
for (int l = 0; l < col; l++) {
vector<int> sums(row, 0);
for (int r = l; r < col; r++) {
for (int i = 0; i < row; i++)
sums[i] += matrix[i][r];
// Find the max subarray no more than K
set<int> sumSet;
sumSet.insert(0);
int curSum = 0;
int curMax = INT_MIN;
for (auto sum:sums) {
curSum += sum;
auto it = sumSet.lower_bound(curSum - k);
if (it != sumSet.end())
curMax = max(curMax, curSum - *it);
sumSet.insert(curSum);
}
ret = max(ret, curMax);
}
}
return ret;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: