[LeetCode] 1031. Maximum Sum of Two Non-Overlapping Subarrays

Posted CNoodle

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode] 1031. Maximum Sum of Two Non-Overlapping Subarrays相关的知识,希望对你有一定的参考价值。

Given an integer array nums and two integers firstLen and secondLen, return the maximum sum of elements in two non-overlapping subarrays with lengths firstLen and secondLen.

The array with length firstLen could occur before or after the array with length secondLen, but they have to be non-overlapping.

A subarray is a contiguous part of an array.

Example 1:

Input: nums = [0,6,5,2,2,5,1,9,4], firstLen = 1, secondLen = 2
Output: 20
Explanation: One choice of subarrays is [9] with length 1, and [6,5] with length 2.

Example 2:

Input: nums = [3,8,1,3,2,1,8,9,0], firstLen = 3, secondLen = 2
Output: 29
Explanation: One choice of subarrays is [3,8,1] with length 3, and [8,9] with length 2.

Example 3:

Input: nums = [2,1,5,6,0,9,5,0,3,8], firstLen = 4, secondLen = 3
Output: 31
Explanation: One choice of subarrays is [5,6,0,9] with length 4, and [0,3,8] with length 3.

Constraints:

  • 1 <= firstLen, secondLen <= 1000
  • 2 <= firstLen + secondLen <= 1000
  • firstLen + secondLen <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

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

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

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

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

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

思路是前缀和 + 动态规划。我参考了这个帖子。因为要快速地找到子数组的和,所以容易想到用前缀和做。注意这道题因为涉及到两个长度不同的子数组 A 和 B,长度分别为 firstLen 和 secondLen,所以需要考虑 A+B 和 B+A 两种情况,谁在前都可以。

具体做法是首先我们把整个数组的前缀和计算好,用一个数组存储,这样当我们需要得到一段子数组的和的时候,我们就可以用 O(1) 的时间拿到。接着我们遍历原数组,在遍历过程中,我们用一个变量 i 表示当前遍历到哪个下标,两个子数组 A 和 B 都在下标 i 的左侧。所以当我们在某个下标 i 的时候,子数组 A 的值 = presum[i - secondLen] - presum[i - secondLen - firstLen],子数组 B 的值 = presum[i] - presum[i - secondLen]。找到两者的最大值再相加,就是最后的结果。

时间O(n)

空间O(n)

Java实现

 class Solution 
     public int maxSumTwoNoOverlap(int[] nums, int firstLen, int secondLen) 
         int n = nums.length;
         int[] presum = new int[n];
         int sum = 0;
         for (int i = 0; i < n; i++) 
             sum += nums[i];
             presum[i] = sum;
         
 
         int max1 = getMax(presum, nums, firstLen, secondLen);
         int max2 = getMax(presum, nums, secondLen, firstLen);
         return Math.max(max1, max2);
     
 
     private int getMax(int[] presum, int[] nums, int firstLen, int secondLen) 
         int maxFirst = 0;
         int max = 0;
         for (int i = firstLen + secondLen - 1; i < nums.length; i++) 
             // 找子数组A的最大值
             maxFirst = Math.max(maxFirst, helper(presum, i - secondLen) - helper(presum, i - secondLen - firstLen));
             // 再找子数组B的最大值
             // 最后再相加
             max = Math.max(max, maxFirst + helper(presum, i) - helper(presum, i - secondLen));
         
         return max;
     
 
     private int helper(int[] presum, int i) 
         if (i == -1) 
             return 0;
         
         return presum[i];
     
 

 

LeetCode 题目总结

[Leetcode] Maximum Subarray

Maximum Subarray 题解

题目来源:https://leetcode.com/problems/maximum-subarray/description/


Description

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

Example

For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.

Solution


class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if (nums.empty())
            return 0;
        int size = nums.size();
        vector<int> dp(size, 0);
        dp[0] = nums[0];
        int max = dp[0];
        for (int i = 1; i < size; i++) {
            dp[i] = (dp[i - 1] > 0 ? dp[i - 1] : 0) + nums[i];
            if (dp[i] > max)
                max = dp[i];
        }
        return max;
    }
};

解题描述

这道题的题意是,对给出的一个数组,求其所有连续区间的最大和。上面给出的解法是使用的是DP,从左向右扫描一遍数组,每一步的问题是:

  • 记最终最大和结果为max,初始值为dp[0]
  • 记当前数组元素为nums[i]
  • 当前数组元素之前的数组区间的临时最大和为dp[i - 1]
    • 如果dp[i - 1]为负,则没有必要加到区间[0, i]的临时最大和上,反之则加上
    • 区间[0, i]的临时最大和为dp[i] = (dp[i - 1] > 0 ? dp[i - 1] : 0) + nums[i]
  • 如果当前临时最大和大于max,则max替换为该值

以上是关于[LeetCode] 1031. Maximum Sum of Two Non-Overlapping Subarrays的主要内容,如果未能解决你的问题,请参考以下文章

1031. Maximum Sum of Two Non-Overlapping Subarrays

Leetcode-1031 Number of Enclaves(飞地的数量)

[Leetcode] Maximum Subarray

[LeetCode]Maximum Subarray

#Leetcode# 53. Maximum Subarray

LeetCode 53. Maximum Subarray