一维/二维 subarray/子矩阵最大和

题目:一维数组找最大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 cumset;
    cumset.insert(0);
    int best = 0, cum = 0;
    for(int i=0; i::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> &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 sums(row, 0);
            for (int r = l; r < col; r++) { // 矩阵的右边界
                for (int i = 0; i < row; i++) // 矩阵每行和更新
                    sums[i] += matrix[i][r]; 
                
                set cumset;
                cumset.insert(0); // 包含从0行到i行,需要减去的和为0
                int cum = 0;
                for (int i = 0; i < row; i++) { // 矩阵的下边界
                    cum += sums[i];
                    set::iterator sit = cumset.lower_bound(cum-k); // 找矩阵的上边界
                    if (sit != cumset.end()) // 能找到符合条件的值,更新res
                        res = max(res, cum-*sit);
                    cumset.insert(cum);
                }
            }
        }
        return res;
    }
};

你可能感兴趣的:(一维/二维 subarray/子矩阵最大和)