篇首语:本文由小常识网(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 题目总结
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的主要内容,如果未能解决你的问题,请参考以下文章