二维前缀和可以在O(nm)的时间复杂度预处理下,在O(1)时间求出任意区域的元素之和。
所以枚举四个边界,在O(1)时间求出区域和,和目标值比较,求最大值,这样的时间复杂度是O(n^2m^2),超时
class Solution {
public:
vector<vector<int>> sums;
int sumRegion(int row1, int col1, int row2, int col2) {
return sums[row2][col2] - sums[row1-1][col2] - sums[row2][col1 - 1] + sums[row1 - 1][col1 - 1];
}
int maxSumSubmatrix(vector<vector<int>>& matrix, int K) {
// 枚举下边界和左右边界,对左右边界进行求和处理
// 找出最合适的上边界
int n = matrix.size(), m = matrix[0].size();
sums.resize(n+1, vector<int>(m+1));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
sums[i][j] = sums[i - 1][j] + sums[i][j - 1] - sums[i - 1][j - 1] + matrix[i - 1][j - 1];
}
}
int res = INT_MIN;
for(int i = 1; i <= n; i++){
for(int j = i; j <= n; j++){
for(int k = 1; k <= m; k++){
for(int p = k; p <= m; p++){
int sum = sumRegion(i, k, j, p);
if(sum <= K){
res = max(res, sum);
}
}
}
}
}
return res;
}
};
如何考虑优化呢?
我们枚举下边界,左边界和右边界,在O(logn)的时间找到一个上边界i,满足
S[j] - S[i] <= k
S[i] >= S[j] - k的最小值,那么就是我们要求的答案
时间复杂度优化到O(nlogn m^2)
class Solution {
public:
vector<vector<int>> sums;
int sumRegion(int row1, int col1, int row2, int col2) {
return sums[row2][col2] - sums[row1-1][col2] - sums[row2][col1 - 1] + sums[row1 - 1][col1 - 1];
}
int maxSumSubmatrix(vector<vector<int>>& matrix, int K) {
// 枚举下边界和左右边界,对左右边界进行求和处理
// 找出最合适的上边界
int n = matrix.size(), m = matrix[0].size();
sums.resize(n+1, vector<int>(m+1));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
sums[i][j] = sums[i - 1][j] + sums[i][j - 1] - sums[i - 1][j - 1] + matrix[i - 1][j - 1];
}
}
int res = INT_MIN;
for(int j = 1; j <= m; j++){
for(int k = j; k <= m; k++){
set<int> s;
s.insert(0);
for(int i = 1; i <=n; i++){
int sum = sumRegion(1, j, i, k);
auto it = s.lower_bound(sum - K);
if(it != s.end()){
res = max(res, sum - *it);
}
s.insert(sum);
}
}
}
return res;
}
};