2023-04-26 LeetCode每日一题(两个非重叠子数组的最大和)

文章介绍了一种使用动态规划解决的问题,即在给定整数数组nums中,找到两个不重叠子数组,使得它们的长度分别为firstLen和secondLen,且元素和最大。解题策略包括计算前缀和、后缀和,并遍历数组以找到最大总和。
摘要由CSDN通过智能技术生成

2023-04-26每日一题

一、题目编号

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

二、题目链接

点击跳转到题目位置

三、题目描述

给你一个整数数组 nums 和两个整数 firstLen 和 secondLen,请你找出并返回两个非重叠 子数组 中元素的最大和,长度分别为 firstLen 和 secondLen 。

长度为 firstLen 的子数组可以出现在长为 secondLen 的子数组之前或之后,但二者必须是不重叠的。

子数组是数组的一个 连续 部分。

四、解题代码

class Solution {
public:
    int maxSumTwoNoOverlap(vector<int>& nums, int firstLen, int secondLen) {
        int n = nums.size();
        int dp[n+5];
        int perfix_firstLen[n+5];
        int perfix_secondLen[n+5];
        int suffix_firstLen[n+5];
        int suffix_secondLen[n+5];
        memset(dp, 0, sizeof(dp));
        memset(perfix_firstLen, 0, sizeof(perfix_firstLen));
        memset(perfix_secondLen, 0, sizeof(perfix_secondLen));
        memset(suffix_firstLen, 0, sizeof(suffix_firstLen));
        memset(suffix_secondLen, 0, sizeof(suffix_secondLen));
        for(int i = 1; i <= n; ++i){
            dp[i] = (dp[i-1] + nums[i-1]);
        }
        for(int i = 0; i <= n; ++i){
            if(i < firstLen){
                perfix_firstLen[i] = -1;
            } else{
                perfix_firstLen[i] = max(perfix_firstLen[i-1], dp[i] - dp[i-firstLen]);
            }
            if(i < secondLen){
                perfix_secondLen[i] = -1;
            } else{
                perfix_secondLen[i] = max(perfix_secondLen[i-1], dp[i] - dp[i-secondLen]);
            }
        }
        for(int i = n; i >= 0; --i){
            if(i + firstLen > n){
                suffix_firstLen[i] = -1;
            } else{
                suffix_firstLen[i] = max(suffix_firstLen[i+1], dp[i+firstLen] - dp[i]);
            }
            if(i + secondLen > n){
                suffix_secondLen[i] = -1;
            } else{
                suffix_secondLen[i] = max(suffix_secondLen[i+1], dp[i+secondLen] - dp[i]);
            }
        }
        int res =  0;
        for(int i = 0; i <= n; ++i){
            if(perfix_firstLen[i] != -1 && suffix_secondLen[i] != -1){
                res = max(res, perfix_firstLen[i] + suffix_secondLen[i]);
            }
            if(perfix_secondLen[i] != -1 && suffix_firstLen[i] != -1){
                res = max(res, perfix_secondLen[i] + suffix_firstLen[i]);
            }
        }
    return res;
    }
};

五、解题思路

(1) 首先我们思考一个问题,分成的两段究竟怎么才能得到最大值。我们取数组下标中的一个位置i,任何不重叠的两端都可以分成i前一段(不包括i所指的元素)和i后一段(包括i所指的元素)。

(2) 按照(1)中所描述的思路,先算出前缀和,这样方便迅速求出长度固定的子数组和。

(3) 分别利用前后缀和,求出下标i前面长度为firstLen和secondLen的子数组最大和,求出下标i(包括下标i)后面长度为firstLen和secondLen的子数组最大和。

(4) 最后利用一遍线性枚举,求出最大值即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值