1031. 两个非重叠子数组的最大和

给出非负整数数组 A ,返回两个非重叠(连续)子数组中元素的最大和,子数组的长度分别为 L 和 M。(这里需要澄清的是,长为 L 的子数组可以出现在长为 M 的子数组之前或之后。)

从形式上看,返回最大的 V,而 V = (A[i] + A[i+1] + ... + A[i+L-1]) + (A[j] + A[j+1] + ... + A[j+M-1]) 并满足下列条件之一:

 

0 <= i < i + L - 1 < j < j + M - 1 < A.length, 或
0 <= j < j + M - 1 < i < i + L - 1 < A.length.
 

示例 1:

输入:A = [0,6,5,2,2,5,1,9,4], L = 1, M = 2
输出:20
解释:子数组的一种选择中,[9] 长度为 1,[6,5] 长度为 2。
示例 2:

输入:A = [3,8,1,3,2,1,8,9,0], L = 3, M = 2
输出:29
解释:子数组的一种选择中,[3,8,1] 长度为 3,[8,9] 长度为 2。
示例 3:

输入:A = [2,1,5,6,0,9,5,0,3,8], L = 4, M = 3
输出:31
解释:子数组的一种选择中,[5,6,0,9] 长度为 4,[0,3,8] 长度为 3。
 

提示:

L >= 1
M >= 1
L + M <= A.length <= 1000
0 <= A[i] <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-sum-of-two-non-overlapping-subarrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:听别人说到了这道题,感觉不难,就写了一下:

           以 i 为轴,用4个数组维护:

           a[i] 代表在[0……i]内长度为L的最大和;          c[i] 代表在[i……size()-1]内的长度L的最大和

           b[i] 代表在[0……i]内长度为M的最大和;          d[i] 代表在[i……size()-1]内的长度M的最大和

           时间复杂度:O(n)

class Solution {
public:
    int a[1005],b[1005],c[1005],d[1005];
    int maxSumTwoNoOverlap(vector<int>& A, int L, int M) {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        memset(d,0,sizeof(d));
        
        vector<int>B;
        for(int i=0;i<A.size();i++) B.push_back(A[i]);
        
        for(int i=B.size()-2;i>=0;i--)   //  后缀
            B[i]+=B[i+1];             
        
        for(int i=1;i<A.size();i++)   // 前缀
            A[i]+=A[i-1];
        
        for(int i=L-1;i<A.size();i++){
            int l=i-L;
            if(l<0)  a[i]=A[i];
            else a[i]=A[i]-A[l];
            if(i>=1) a[i]=max(a[i],a[i-1]);
        }
        
        for(int i=B.size()-L;i>=0;i--){
            int r=i+L;
            if(r>=B.size())  c[i]=B[i];
            else c[i]=B[i]-B[r];
            c[i]=max(c[i],c[i+1]);
        }
        
        //  ---------------------------------------
        
        for(int i=M-1;i<A.size();i++){
            int l=i-M;
            if(l<0)  b[i]=A[i];
            else b[i]=A[i]-A[l];
            if(i>=1) b[i]=max(b[i],b[i-1]);
        }
        
        for(int i=B.size()-M;i>=0;i--){
            int r=i+M;
            if(r>=B.size())  d[i]=B[i];
            else d[i]=B[i]-B[r];
            d[i]=max(d[i],d[i+1]);
        }
        
        int ans=0;
        
        for(int i=L-1;i<A.size();i++){    //  L 在前,M 在后
            int k=A.size()-i-1;
            if(k<M)  break;
            ans=max(ans,a[i]+d[i+1]);
        }
        
        for(int i=M-1;i<A.size();i++){    //  M 在前,L 在后
            int k=A.size()-i-1;
            if(k<L)  break;
            ans=max(ans,b[i]+c[i+1]);
        }
        
        return ans;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值