【Leetcode】Max Sum of Rectangle No Larger Than K

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?
leetcode题目链接

TLE。。。,技穷,伪dp加暴力破解

class Solution {
public:
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        int h = matrix.size();
        if (h < 0) return 0;
        int l = matrix[0].size();
        vector<vector<int> > dp(h, vector<int>(l, 0));
        int res = matrix[0][0] <= k ? matrix[0][0] : INT_MIN;
        dp[0][0] = matrix[0][0];
        for (int i = 1; i < h; i++)
        {
            dp[i][0] = dp[i - 1][0] + matrix[i][0];
            if (matrix[i][0] <= k)
                res = max(res, matrix[i][0]);
            if (dp[i][0] <= k)
                    res = max(res, dp[i][0]);
        }

        for (int j = 1; j < l; j++)
        {
            dp[0][j] = dp[0][j - 1] + matrix[0][j];
            if (matrix[0][j] <= k)
                res = max(res, matrix[0][j]);
            if (dp[0][j] <= k)
                    res = max(res, dp[0][j]);
        }

        for (int i = 1; i < h; i++)
            for (int j = 1; j < l; j++)
            {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + matrix[i][j];
                if (matrix[i][j] <= k)
                    res = max(res, matrix[i][j]);
                if (dp[i][j] <= k)
                    res = max(res, dp[i][j]);
            }

        for (int i = 0; i < h; i++)
            for (int j = 0; j < l; j++)
                for (int m = j + 1; m < l; m++)
                {
                    int temp = dp[i][m] - dp[i][j] + matrix[i][j];
                    if (temp <= k) res = max(temp, res);
                }

        for (int i = 0; i < l; i++)
            for (int j = 0; j < h; j++)
                for (int m = j + 1; m < h; m++)
                {
                    int temp = dp[m][i] - dp[j][i] + matrix[j][i];
                    if (temp <= k) res = max(temp, res);
                }

        for (int i = 0; i < h; i++)
            for (int j = 0; j < l; j++)
            {
                if (i == 0 && j == 0) continue;
                for (int m = i + 1; m < h; m++)
                    for (int n = j + 1; n < l; n++)
                    {
                        int temp;
                        if (i == 0) 
                        {
                            temp = dp[m][n] - dp[m][j - 1];
                        }
                        else if(j == 0)
                        {
                            temp = dp[m][n] - dp[i - 1][n];
                        }
                        else
                        {
                            temp = dp[m][n] + dp[i-1][j-1] - dp[m][j - 1] - dp[i - 1][n];
                        }
                        if (temp <= k) res = max(temp, res);
                    }
            }

        return res;
    }
};

改进版:(依然TLE)

class Solution {
public:
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        if (matrix.empty()) return 0;
    int row = matrix.size(), col = matrix[0].size(), res = 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];
            }
           vector<vector<int> > dp(row,vector<int>(row,0));
           for(int i=0;i<row;i++)
           {
               dp[i][i] = sums[i];
               if(dp[i][i] <= k)
               res = std::max(res, dp[i][i]);
           }
           for(int i=0;i<row;i++)
           {
               for(int j=i+1;j<row;j++)
               {
                   dp[i][j] = dp[i][j-1] + sums[j];
                    if(dp[i][j] <= k)
                    res = std::max(res, dp[i][j]);
               }
           }

        }
    }
    return res;
    }
};

网上的解法

class Solution {
public:
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        if (matrix.empty()) return 0;
    int row = matrix.size(), col = matrix[0].size(), res = 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> accuSet;
            accuSet.insert(0);
            int curSum = 0, curMax = INT_MIN;
            for (int sum : sums) {
                curSum += sum;
                set<int>::iterator it = accuSet.lower_bound(curSum - k);
                if (it != accuSet.end()) curMax = std::max(curMax, curSum - *it);
                accuSet.insert(curSum);
            }
            res = std::max(res, curMax);
        }
    }
    return res;
    }
};

上边的算法的解题关键是把问题转化成了多个一维的问题,然后通过求解一维的问题解决问题,然后一维的问题的解法是一个o(nlog2n),set里边永远都是满足条件的最小值,因为set是按照从小到大的顺序排列的,所有的sum都进行了排列

Given an array of integers A and an integer k, find a subarray that contains the largest sum, subject to a constraint that the sum is less than k?
First thing to note is that sum of subarray (i,j](i,j] is just the sum of the first jj elements less the sum of the first ii elements. Store these cumulative sums in the array cum. Then the problem reduces to finding i,ji,j such that i
To solve this, scan from left to right. Put the cum[i]cum[i] values that you have encountered till now into a set. When you are processing cum[j]cum[j] what you need to retrieve from the set is the smallest number in the set such which is bigger than cum[j]−kcum[j]−k. This lookup can be done in O(logn)O(log⁡n) using upper_bound. Hence the overall complexity is O(nlog(n))O(nlog⁡(n)).
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值