【Leetcode】Max Sum of Rectangle No Larger Than K

来源:互联网 发布:网络对青少年的危害 编辑:程序博客网 时间:2024/05/17 05:01

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)).
0 0