zoukankan      html  css  js  c++  java
  • [LeetCode] 363. Max Sum of Rectangle No Larger Than K 最大矩阵和不超过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:

    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 同步地址:

    https://github.com/grandyang/leetcode/issues/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 题目讲解汇总(持续更新中...)

  • 相关阅读:
    dp思维
    快速幂+地推
    背包问题找物品
    石子合并问题
    hihocoder 1580 Matrix(北京icpc2017网络赛)
    ACM对拍造数据
    主席树学习小结(POJ 2104)
    莫队算法入门 BZOJ 2038
    hdu 2586
    Kattis
  • 原文地址:https://www.cnblogs.com/grandyang/p/5617660.html
Copyright © 2011-2022 走看看