题目:一维数组找最大subarray和,O(n)。
题目:二维矩阵找最大子矩阵和,O(min(m, n)^2 * max(m, n))。见编程之美。
题目:一维数组找最大subarray和,和不大于k。不能包含0个元素。
思路:subarray(i,j]的和等于subarray[0,j]-subarray[0,i],则需要找到一个subarray[0,j]-subarray[0,i]<=k,即subarray[0,i]>=subarray[0,j]-k,j确定时候,想找一个最小的subarray[0,i]。
则为遍历结束位置j,找到最小i,并且满足subarray[0,i]>=subarray[0,j]-k。
外层循环为O(N),内层为了找lower_bound,将之前的子数组和用排序的set,插入元素为O(logN),有序set找lower_bound也是O(logN),最后是O(NlogN)。
int best_cumulative_sum(int ar[],int N,int K)
{
set<int> cumset;
cumset.insert(0);
int best = 0, cum = 0;
for(int i=0; i<N; i++)
{
cum += ar[i];
set<int>::iterator sit = cumset.lower_bound(cum-K);
if(sit != cumset.end())
best = max(best, cum-*sit);
cumset.insert(cum);
}
return best;
}
题目:二维矩阵找最大子矩阵和,和不大于k。不能包含0个元素。
思路:时间 O[min(m,n)^2 x max(m,n) x log(max(m,n))],空间 O(max(m, n))。
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>> &matrix, int k) {
if (matrix.empty()) return 0;
int row = matrix.size(), col = matrix[0].size();
int res = INT_MIN; // 不准许包含0个单词
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];
set<int> cumset;
cumset.insert(0); // 包含从0行到i行,需要减去的和为0
int cum = 0;
for (int i = 0; i < row; i++) { // 矩阵的下边界
cum += sums[i];
set<int>::iterator sit = cumset.lower_bound(cum-k); // 找矩阵的上边界
if (sit != cumset.end()) // 能找到符合条件的值,更新res
res = max(res, cum-*sit);
cumset.insert(cum);
}
}
}
return res;
}
};