Maximum Sum of Two Non-Overlapping Subarrays

medium prefix sum sliding window array

Problem

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 subarrays may appear in either order, but they must not overlap.

Inputnums = [0, 6, 5, 2, 2, 5, 1, 9, 4], firstLen = 1, secondLen = 2
Output20
Pick [9] (length 1) and [6, 5] (length 2) → 9 + 11 = 20. The two windows do not overlap.

def max_sum_two_no_overlap(nums, first_len, second_len):
    n = len(nums)
    prefix = [0] * (n + 1)
    for i in range(n):
        prefix[i + 1] = prefix[i] + nums[i]

    def best(L, M):
        # L-window before M-window
        max_l = best_sum = 0
        for i in range(L + M, n + 1):
            max_l = max(max_l, prefix[i - M] - prefix[i - M - L])
            best_sum = max(best_sum, max_l + prefix[i] - prefix[i - M])
        return best_sum

    return max(best(first_len, second_len), best(second_len, first_len))
function maxSumTwoNoOverlap(nums, firstLen, secondLen) {
  const n = nums.length;
  const prefix = new Array(n + 1).fill(0);
  for (let i = 0; i < n; i++) prefix[i + 1] = prefix[i] + nums[i];

  function best(L, M) {
    let maxL = 0, bestSum = 0;
    for (let i = L + M; i <= n; i++) {
      maxL = Math.max(maxL, prefix[i - M] - prefix[i - M - L]);
      bestSum = Math.max(bestSum, maxL + prefix[i] - prefix[i - M]);
    }
    return bestSum;
  }

  return Math.max(best(firstLen, secondLen), best(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(best(prefix, n, firstLen, secondLen),
                        best(prefix, n, secondLen, firstLen));
    }

    private int best(int[] prefix, int n, int L, int M) {
        int maxL = 0, bestSum = 0;
        for (int i = L + M; i <= n; i++) {
            maxL = Math.max(maxL, prefix[i - M] - prefix[i - M - L]);
            bestSum = Math.max(bestSum, maxL + prefix[i] - prefix[i - M]);
        }
        return bestSum;
    }
}
int best(vector<int>& prefix, int n, int L, int M) {
    int maxL = 0, bestSum = 0;
    for (int i = L + M; i <= n; i++) {
        maxL = max(maxL, prefix[i - M] - prefix[i - M - L]);
        bestSum = max(bestSum, maxL + prefix[i] - prefix[i - M]);
    }
    return bestSum;
}

int maxSumTwoNoOverlap(vector<int>& nums, int firstLen, int secondLen) {
    int n = nums.size();
    vector<int> prefix(n + 1, 0);
    for (int i = 0; i < n; i++) prefix[i + 1] = prefix[i] + nums[i];
    return max(best(prefix, n, firstLen, secondLen),
               best(prefix, n, secondLen, firstLen));
}
Time: O(n) Space: O(n)