363、矩形区域不超过K的最大数值和

  1. 363、矩形区域不超过K的最大数值和
    1. 示例:
  • 题解
    1. 1、最大前缀和的二维形式
  • 363、矩形区域不超过K的最大数值和

    给定一个非空二维矩阵 matrix 和一个整数 k,找到这个矩阵内部不大于 k 的最大矩形和。

    示例:

    输入: matrix = [[1,0,1],[0,-2,3]], k = 2
    输出: 2 
    解释: 矩形区域 [[0, 1], [-2, 3]] 的数值和是 2,且 2 是不超过 k 的最大数字(k = 2)。
    

    说明:

    • 矩阵内的矩形区域面积必须大于 0。
    • 如果行数远大于列数,你将如何解答呢?

    题解

    1、最大前缀和的二维形式

    • 求每一行的前缀和

    • 穷举所有矩形,求其和

      • 更新最大值
      • 若求的的值等于k, 直接返回
    • 代码

    // c++
    class Solution {
    public:
        // n行数,m列数
        // O(m^2 * nlog(n)) 对所有可能的左右边界,在前缀和的基础上求小于k的最大连续子数组和
        int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
            int n = matrix.size(), m = matrix[0].size();
            // 预处理前缀和,求每一行的前缀和
            vector<vector<int>> v(n + 1, vector<int>(m + 1, 0));
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    v[i][j] = v[i][j - 1] + matrix[i - 1][j - 1];
                }
            }
    
            // 两个for遍历所有可能的左右边界
            int res = INT_MIN;
            // 对于每一列
            for (int l = 1; l <= m; l++) {
                // 从第l列开始,遍历剩余的列
                for (int r = l; r <= m; r++) {
                    // 存set,set查询lower_bound O(log(n))
                    set<int> st;
                    st.insert(0);
                    int cur = 0;
                    // 对于每一行,求可能的矩阵
                    for (int i = 1; i <= n; i++) {
                        // 第i-1行中l-r直接的数之和
                        int now = v[i][r] - v[i][l - 1];
                        cur += now;
                        // 对于当前的前缀和,找数中大于等于cur-k的最小元素
                        // 设找到的数为p,则p大于等于cur-k,必有 cur - p <= k
                        // 所有最小的p,使得cur-p的值最大,且该值小于等于k
    
                        // lower_bound()返回值是一个迭代器,返回指向大于等于key的第一个值的位置
                        auto it = st.lower_bound(cur - k);
                        // 更新最大值
                        if (it != st.end()) res = max(res, cur - *it);
                        st.insert(cur);
                        // 找到最大值,提前结束
                        if (res == k) return res;
                    }
                }
            }
    
            return res;
        }
    };
    
    // 作者:zhenying
    // 链接:https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/solution/cpp-86-qian-zhui-he-chu-li-by-zhenying/
    
    • 16ms
    class Solution {
    public:
        int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
            int n = matrix.size();
            if (n == 0) return 0;
            int m = matrix[0].size();
            if (m == 0) return 0;
            int res = INT_MIN;
            // 对于所有的列
            for (int s = 0; s < m; ++s) {
                // 申请一个大小等于行数的数组
                vector<int> rowSum(n, 0);
                // 从第s列开始的所有列
                for (int e = s; e < m; ++e) {
                    // 记录矩阵和
                    int maxSum = 0;
                    // 对于行求和
                    for (int i = 0, acc = 0; i < n; ++i) {
                        rowSum[i] += matrix[i][e];
                        acc += rowSum[i];// 累加
                        // 这个表达式有点意思
                        acc <= k && res < acc ? res = acc : 0;
                        acc < 0 ? acc = 0 : maxSum = max(maxSum, acc);
                    }
                    // 找到最大解,提前结束
                    if (res == k) return k;
                    // 否则继续循环,继续叠加
                    if (maxSum < k) continue;
                    // 集合
                    set<int> hash{0};
                    for (int i = 0, acc = 0; i < n; ++i) {
                        acc += rowSum[i];// 累加
                        // 求hash中第一个大于等于acc-k的下标
                        auto iter = hash.lower_bound(acc - k);
                        iter != hash.end() && res < acc - *iter ? res = acc - *iter : 0;
                        hash.insert(acc);
                    }
                    // 提前结束
                    if (res == k) return k;
                }
            }
            return res;
        }
    };
    

    转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

    💰

    Title:363、矩形区域不超过K的最大数值和

    Count:853

    Author:攀登

    Created At:2020-07-26, 00:19:44

    Updated At:2024-06-15, 15:52:32

    Url:http://jiafeimao-gjf.github.io/2020/07/26/363%E3%80%81%E7%9F%A9%E5%BD%A2%E5%8C%BA%E5%9F%9F%E4%B8%8D%E8%B6%85%E8%BF%87K%E7%9A%84%E6%9C%80%E5%A4%A7%E6%95%B0%E5%80%BC%E5%92%8C/

    Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

    ×

    Help us with donation