Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 363. Max Sum of Rectangle No Larger Than K #363

Open
grandyang opened this issue May 30, 2019 · 0 comments
Open

[LeetCode] 363. Max Sum of Rectangle No Larger Than K #363

grandyang opened this issue May 30, 2019 · 0 comments

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

 

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:

  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?

Credits:
Special thanks to @fujiaozhu for adding this problem and creating all test cases.

 

这道题给了我们一个二维数组,让求和不超过的K的最大子矩形,那么首先可以考虑使用 brute force 来解,就是遍历所有的子矩形,然后计算其和跟K比较,找出不超过K的最大值即可。就算是暴力搜索,也可以使用优化的算法,比如建立累加和,参见之前那道题 Range Sum Query 2D - Immutable,可以快速求出任何一个区间和,下面的方法就是这样的,当遍历到 (i, j) 时,计算 sum(i, j),表示矩形 (0, 0) 到 (i, j) 的和,然后遍历这个矩形中所有的子矩形,计算其和跟K相比,这样既可遍历到原矩形的所有子矩形,参见代码如下:

 

解法一:

class Solution {
public:
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        if (matrix.empty() || matrix[0].empty()) return 0;
        int m = matrix.size(), n = matrix[0].size(), res = INT_MIN;
        int sum[m][n];
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                int t = matrix[i][j];
                if (i > 0) t += sum[i - 1][j];
                if (j > 0) t += sum[i][j - 1];
                if (i > 0 && j > 0) t -= sum[i - 1][j - 1];
                sum[i][j] = t;
                for (int r = 0; r <= i; ++r) {
                    for (int c = 0; c <= j; ++c) {
                        int d = sum[i][j];
                        if (r > 0) d -= sum[r - 1][j];
                        if (c > 0) d -= sum[i][c - 1];
                        if (r > 0 && c > 0) d += sum[r - 1][c - 1];
                        if (d <= k) res = max(res, d);
                    }
                }
            }
        }
        return res;
    }
};

 

下面这个算法进一步的优化了运行时间,这个算法是基于计算二维数组中最大子矩阵和的算法,可以参见 youtube 上的这个视频。这个算法巧妙在把二维数组按行或列拆成多个一维数组,然后利用一维数组的累加和来找符合要求的数字,这里用了 lower_bound 来加快的搜索速度,也可以使用二分搜索法来替代。建立一个 TreeSet,然后开始先放个0进去,为啥要放0呢,因为要找 lower_bound(curSum - k),当 curSum 和k相等时,0就可以被返回了,这样就能更新结果了。由于对于一维数组建立了累积和,那么 sum[i,j] = sum[i] - sum[j],其中 sums[i,j] 就是目标子数组需要其和小于等于k,然后 sums[j] 是 curSum,而 sum[i] 就是要找值,当使用二分搜索法找 sum[i] 时,sum[i] 的和需要大于等于 sum[j] - k,所以也可以使用 lower_bound 来找,参见代码如下:

 

解法二:

class Solution {
public:
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        if (matrix.empty() || matrix[0].empty()) return 0;
        int m = matrix.size(), n = matrix[0].size(), res = INT_MIN;
        for (int i = 0; i < n; ++i) {
            vector<int> sum(m);
            for (int j = i; j < n; ++j) {
                for (int k = 0; k < m; ++k) {
                    sum[k] += matrix[k][j];
                }
                int curSum = 0;
                set<int> st{{0}};
                for (auto a : sum) {
                    curSum += a;
                    auto it = st.lower_bound(curSum - k);
                    if (it != st.end()) res = max(res, curSum - *it);
                    st.insert(curSum);
                }
            }
        }
        return res;
    }
};

 

Github 同步地址:

#363

 

类似题目:

Maximum Subarray

Range Sum Query 2D - Immutable

Maximum Size Subarray Sum Equals k

 

参考资料:

https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/

https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/discuss/83618/2-Accepted-Java-Solution

https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/discuss/83599/Accepted-C%2B%2B-codes-with-explanation-and-references

 

LeetCode All in One 题目讲解汇总(持续更新中...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant