LeetCode 1031. Maximum Sum of Two Non-Overlapping Subarrays

链接:https://leetcode.com/problems/maximum-sum-of-two-non-overlapping-subarrays/

思路

Approach 1: 假设L子串在M子串左边。反向迭代A,到达位置i时,计算M子串[i, i+M)总和,并记录到i时已计算的M子串总和的最大值maxMSum[i]。然后正向迭代A,到达位置i时,此时已知的两串总和最大为maximal,计算L子串[i, i+L)总和,记为sum(i, L),则maximal = max(maximal, sum(i, L) + maxMSum[i+L])。注意计算子串总和时要利用上次的计算结果,以减少相加次数。然后再算L在M右边情况,取两种情况最大值为最终结果。时间复杂度O(n).
Approach 2: 大体与1相同,只是在求区间和时不累加,而是先算prefixSum,再算rangeSum

代码

approach 1


class Solution {
public:
    int maxSumTwoNoOverlap(vector<int>& A, int L, int M) {
        return max(helper(A, L, M), helper(A, M, L));
    }
private:
    int helper(vector<int>& A, int L, int M) {
        int n = A.size();
        vector<int> maxMSum(n); // maxMSum[i]表示[i, end)最大M的和
        int start = n - M, prev = accumulate(A.begin()+start, A.end(), 0); // 最右M子串
        maxMSum[start] = prev;
        for(int i = start - 1; i >= L; i--) { // i >= L,给L子串留出空间
            prev = prev + A[i] - A[i+M];
            maxMSum[i] = max(prev, maxMSum[i+1]);
        }
        prev = accumulate(A.begin(), A.begin()+L, 0); // 最左L子串
        int maximal = prev + maxMSum[L];
        for(int i = 1; i < n - L; i++) {
            prev = prev + A[i-1+L] - A[i-1];
            maximal = max(maximal, prev + maxMSum[i+L]);
        }
        return maximal;
    }
};

approach 2

class Solution {
public:
    int maxSumTwoNoOverlap(vector<int>& A, int L, int M) {
        int prev = 0;
        for(auto x : A) {
            prefixSum.push_back(prev += x);
        }
        return max(helper(L, M), helper(M, L));
    }
private:
    vector<int> prefixSum;
    int rangeSum(int i, int j) {
        return prefixSum[j] - (i == 0 ? 0 : prefixSum[i-1]);
    }
    // 设L在左,M在右
    int helper(int L, int M) {
        int n = prefixSum.size();
        vector<int> maxMSum(n); // maxMSum[i]表示[i, end)最大M的和
        int start = n - M;
        maxMSum[start] = rangeSum(start, n-1); // 最右M子串
        for(int i = start - 1; i >= L; i--) {
            maxMSum[i] = max(rangeSum(i, i+M-1), maxMSum[i+1]);
        }
        int maximal = rangeSum(0, L-1) + maxMSum[L];
        for(int i = 1; i < n - L; i++) {
            maximal = max(maximal, rangeSum(i, i+L-1) + maxMSum[i+L]);
        }
        return maximal;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值