689. Maximum Sum of 3 Non-Overlapping Subarrays

In a given array nums of positive integers, find three non-overlapping subarrays with maximum sum.

Each subarray will be of size k, and we want to maximize the sum of all 3*k entries.

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:

Input: [1,2,1,2,6,7,5,1], 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.

Note:

nums.length will be between 1 and 20000.

nums[i] will be between 1 and 65535.

k will be between 1 and floor(nums.length / 3).

這題需要計算subarray的和,需要建立一個accumulative sums array來幫助獲得各個subarray的和。另外建立兩個DP array, left and right去分別紀錄某個點左邊擁有最大和的子數列起始位置,以及右邊擁有最大和的子數列起始位置。最後再把所有可能的中間子數列起始點掃描一遍,取得左邊和右邊最大的子數列和。

// Dynamic Programming + accumulative sum
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) { // time: O(n); space: O(n)
    if (nums.empty() || k == 0) return {};
    int n = nums.size();
    // sums is accumulative sum array
    // left[i]: the starting index of the subarray[0...i] with the largest sum
    // right[i]: the starting index of the subarray[i...n-1] with the largest sum
    vector<int> res, sums({0}), left(n, 0), right(n, n - k);
    // build accumulative sums
    for (int num : nums) sums.push_back(sums.back() + num);
    // build left dp array
    for (int i = k, total = sums[k] - sums[0]; i < n; ++i) { // index is the end of the left subarray
        if (sums[i + 1] - sums[i - k + 1] > total) {
            left[i] = i - k + 1;
            total = sums[i + 1] - sums[i - k + 1];
        } else {
            left[i] = left[i - 1];
        }
    }
    // build right dp array
    for (int i = n - 1 - k, total = sums[n] - sums[n - k]; i >= 0; --i) { // index is the start of the right subarray
        if (sums[i + k] - sums[i] >= total) {
            right[i] = i;
            total = sums[i + k] - sums[i];
        } else {
            right[i] = right[i + 1];
        }
    }
    // loop through all possible middle subarray
    int global_max = INT_MIN;
    for (int i = k; i <= n - 2 * k; ++i) { // index is the start of the middle subarray
        int l = left[i - 1], r = right[i + k];
        int total = (sums[l + k] - sums[l]) + (sums[i + k] - sums[i]) + (sums[r + k] - sums[r]);
        if (global_max < total) {
            global_max = total;
            res = {l, i, r};
        }
    }
    return res;
}

Last updated

Was this helpful?