Skip to content

689. Maximum Sum of 3 Non-Overlapping Subarrays

Description

Given an integer array nums and an integer k, find three non-overlapping subarrays of length k with maximum sum and return them.

Return the result as a list of indices representing the starting position of each interval (0-indexed). If there are multiple answers, return the lexicographically smallest one.

 

Example 1:

Input: nums = [1,2,1,2,6,7,5,1], k = 2
Output: [0,3,5]
Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.

Example 2:

Input: nums = [1,2,1,2,1,2,1,2,1], k = 2
Output: [0,2,4]

 

Constraints:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] < 216
  • 1 <= k <= floor(nums.length / 3)

 

Solutions

Solution: Prefix Sum + Dynamic Programming

  • Time complexity: O(n)
  • Space complexity: O(n)

 

JavaScript

js
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
const maxSumOfThreeSubarrays = function (nums, k) {
  const n = nums.length;
  const prefixSum = new Array(n).fill(0);
  const leftDp = new Array(n).fill(0);
  const rightDp = new Array(n).fill(n - k);

  prefixSum[-1] = 0;

  for (let index = 0; index < n; index++) {
    prefixSum[index] = prefixSum[index - 1] + nums[index];
  }
  const getSubSum = index => prefixSum[index + k - 1] - prefixSum[index - 1];
  let maxSum = prefixSum[k - 1];

  for (let index = 1; index < n; index++) {
    const currentSum = getSubSum(index);

    if (currentSum > maxSum) {
      maxSum = currentSum;
      leftDp[index] = index;
      continue;
    }
    leftDp[index] = leftDp[index - 1];
  }
  maxSum = prefixSum[n - 1] - prefixSum[n - k - 1];

  for (let index = n - k - 1; index >= 0; index--) {
    const currentSum = getSubSum(index);

    if (currentSum >= maxSum) {
      maxSum = currentSum;
      rightDp[index] = index;
      continue;
    }
    rightDp[index] = rightDp[index + 1];
  }
  let result = [];

  maxSum = 0;

  for (let index = k; index <= n - k * 2; index++) {
    const left = leftDp[index - k];
    const right = rightDp[index + k];
    const sum = getSubSum(left) + getSubSum(index) + getSubSum(right);

    if (sum <= maxSum) continue;
    result = [left, index, right];
    maxSum = sum;
  }
  return result;
};

Released under the MIT license