0%

4-26每日

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

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

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

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

示例 1:

输入:nums = [0,6,5,2,2,5,1,9,4], firstLen = 1, secondLen = 2
输出:20
解释:子数组的一种选择中,[9] 长度为 1,[6,5] 长度为 2。

题解

1031-c.png

代码

class Solution {
public:
    int maxSumTwoNoOverlap(vector &nums, int firstLen, int secondLen) {
        int ans = 0, n = nums.size(), s[n + 1]; // 定义变量
        s[0] = 0;
        partial_sum(nums.begin(), nums.end(), s + 1); // partial_sum 函数计算 nums 的前缀和

        // 定义一个 lambda 函数对象,用于计算两个相离的子数组的最大和
        auto f = [&](int firstLen, int secondLen) {
            int maxSumA = 0;
            for (int i = firstLen + secondLen; i <= n; ++i) { // 遍历 s 数组,计算 A、B 两个子数组的最大和
                // 计算 A 子数组的最大和
                maxSumA = max(maxSumA, s[i - secondLen] - s[i - secondLen - firstLen]);
                // 计算 A、B 两个子数组的总和,并更新最大值
                ans = max(ans, maxSumA + s[i] - s[i - secondLen]);
            }
        };

        // 分别计算左 a 右 b 和左 b 右 a 两个方案的最大和,并取两个方案的最大值
        f(firstLen, secondLen); // 左 a 右 b
        f(secondLen, firstLen); // 左 b 右 a
        return ans; // 返回最大和
    }
};