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都进行了排列