Maximum Sum of Two Non-Overlapping Subarrays
MedPrompt
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 <= 10002 <= firstLen + secondLen <= 1000firstLen + secondLen <= nums.length <= 10000 <= nums[i] <= 1000
Approaches
3 approaches with complexity analysis and trade-offs.
This approach improves upon the brute force by avoiding redundant calculations. It breaks the problem into two cases: the first subarray appears before the second, and vice-versa. It then uses dynamic programming ideas to solve each case in linear time.
Algorithm
- Create a helper function
solve(prefix, L, M). - Inside
solve:- Initialize
maxLsum = 0andmaxTotal = 0. - Iterate
ifromL + Mton:- Calculate sum of L-subarray ending at
i - M - 1:sumL = prefix[i - M] - prefix[i - M - L]. - Update
maxLsum = max(maxLsum, sumL). - Calculate sum of M-subarray ending at
i - 1:sumM = prefix[i] - prefix[i - M]. - Update
maxTotal = max(maxTotal, maxLsum + sumM).
- Calculate sum of L-subarray ending at
- Return
maxTotal.
- Initialize
- In the main function:
- Calculate prefix sums for
nums. - Call
res1 = solve(prefix, firstLen, secondLen). - Call
res2 = solve(prefix, secondLen, firstLen). - Return
max(res1, res2).
- Calculate prefix sums for
Walkthrough
The core idea is to solve two separate, symmetric problems and take the maximum of their results:
- Max sum with a
firstLensubarray appearing before asecondLensubarray. - Max sum with a
secondLensubarray appearing before afirstLensubarray.
Let's focus on case 1. We can write a helper function solve(L, M) for this. We iterate through the array, considering each possible position for the M-length subarray. For each position, we need the maximum sum of an L-length subarray that appears entirely before it. To do this efficiently, as we iterate from left to right with a split point, we can keep track of the maximum L-length subarray sum seen so far to the left of the split point. We first compute a prefix sum array to get subarray sums in O(1). The solve(L, M) function works as follows:
- Initialize
maxL(max sum of an L-subarray) andmaxTotal. - Iterate
ifromL + Mton. The indexirepresents the end of the combined window. - The
M-length subarray ends ati-1. Its sum issumM. - The
L-length subarray must end at or beforei - M - 1. We updatemaxLby considering the newL-length subarray that just became available (the one ending ati - M - 1). - We then update
maxTotalwithmaxL + sumM.
The final result is max(solve(firstLen, secondLen), solve(secondLen, firstLen)).
class Solution { public int maxSumTwoNoOverlap(int[] nums, int firstLen, int secondLen) { int n = nums.length; int[] prefix = new int[n + 1]; for (int i = 0; i < n; i++) { prefix[i + 1] = prefix[i] + nums[i]; } return Math.max( findMaxSum(prefix, firstLen, secondLen), findMaxSum(prefix, secondLen, firstLen) ); } private int findMaxSum(int[] prefix, int L, int M) { int n = prefix.length - 1; int maxL = 0; int maxTotal = 0; // Window of L+M, M is the second subarray for (int i = L + M; i <= n; i++) { // Max L-sum subarray in the first part [0, i-M-1] int sumL = prefix[i - M] - prefix[i - M - L]; maxL = Math.max(maxL, sumL); // M-sum subarray in the second part [i-M, i-1] int sumM = prefix[i] - prefix[i - M]; maxTotal = Math.max(maxTotal, maxL + sumM); } return maxTotal; }}Complexity
Time
O(N), where N is the length of `nums`. We make a single pass to compute prefix sums, and then two more passes inside the helper function.
Space
O(N) to store the prefix sum array.
Trade-offs
Pros
Much more efficient than the brute-force approach with a linear time complexity.
Cons
Requires extra space for the prefix sum array.
Solutions
Solution
class Solution {public int maxSumTwoNoOverlap(int[] nums, int firstLen, int secondLen) { int n = nums.length; int[] s = new int[n + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + nums[i]; } int ans = 0; for (int i = firstLen, t = 0; i + secondLen - 1 < n; ++i) { t = Math.max(t, s[i] - s[i - firstLen]); ans = Math.max(ans, t + s[i + secondLen] - s[i]); } for (int i = secondLen, t = 0; i + firstLen - 1 < n; ++i) { t = Math.max(t, s[i] - s[i - secondLen]); ans = Math.max(ans, t + s[i + firstLen] - s[i]); } return ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.