• 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.
    2. 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;
        }
    };
  • 相关阅读:
    12月19号 init和class
    12月18号 property关键字
    12月18号 属性property
    12月17号 类和对象
    12月17号 OC语言准备
    12月16号 文件操作
    12月16号 双链表
    12月15号 单链表
    2015.12.07 ATM
    2015.12.03 命名规范 输入输出 运算符 条件语句 循环语句
  • 原文地址:https://www.cnblogs.com/zhoudayang/p/5679496.html
Copyright © 2020-2023  润新知