689. Maximum Sum of 3 Non-Overlapping Subarrays

Description

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).

Solution

DFS (TLE)

DP

The question asks for three non-overlapping intervals with maximum sum of all 3 intervals. If the middle interval is [i, i+k-1], where k <= i <= n-2k, the left interval has to be in subrange [0, i-1], and the right interval is from subrange [i+k, n-1].

So the following solution is based on DP.

  • posLeft[i] is the starting index for the left interval in range [0, i];
  • posRight[i] is the starting index for the right interval in range [i, n-1];

Then we test every possible starting index of middle interval, i.e. k <= i <= n-2k, and we can get the corresponding left and right max sum intervals easily from DP. And the run time is O(n).

Caution. In order to get lexicographical smallest order, when there are two intervals with equal max sum, always select the left most one. So in the code, the if condition is ">= tot" for right interval due to backward searching, and "> tot" for left interval.

class Solution {
    public int[] maxSumOfThreeSubarrays(int[] nums, int k) {
        int n = nums.length;
        int[] sum = new int[n + 1];
        for (int i = 0; i < n; ++i) {
            sum[i + 1] = nums[i] + sum[i];
        }
        // leftPos[i] = j means [j, j + k) is the max of [0, i]
        int[] leftPos = new int[n]; 
        for (int i = k, tot = getKSum(sum, 0, k); i < n; ++i) {
            if (getKSum(sum, i - k + 1, k) > tot) {
                leftPos[i] = i - k + 1;
                tot = getKSum(sum, i - k + 1, k);
            } else {
                leftPos[i] = leftPos[i - 1];
            }
        }
        
        int[] rightPos = new int[n];
        rightPos[n - k] = n - k;
        
        for (int i = n - k - 1, tot = getKSum(sum, n - k, k); i >= 0; --i) {
            if (getKSum(sum, i, k) >= tot) {
                rightPos[i] = i;
                tot = getKSum(sum, i, k);
            } else {
                rightPos[i] = rightPos[i + 1];
            }
        }
        
        int[] res = new int[3];
        int maxSum = 0;
        for (int i = k; i <= n - 2 * k; ++i) {
            int curr = getKSum(sum, i, k) 
                + getKSum(sum, leftPos[i - 1], k) 
                + getKSum(sum, rightPos[i + k], k);
            if (curr > maxSum) {
                maxSum = curr;
                res[0] = leftPos[i - 1];
                res[1] = i;
                res[2] = rightPos[i + k];
            }
        }
        
        return res;
    }
    
    public int getKSum(int[] sum, int start, int k) {
        return sum[start + k] - sum[start];
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 12,173评论 0 10
  • “楷妈”出现在我生活中也有一年多了。最初看到是在海媚老师朋友圈,老师一开始推广柠檬膏。我没有心动,直到怀姜膏的...
    欢子fly_楷妈养生合伙人阅读 2,454评论 0 0
  • 妖精 西游记里的妖精们那是一个个貌美,妖娆妩媚!不但武功了得,对喜欢的人那是使出百般浑身解数吸引,活的如此...
    7c5489ad8902阅读 1,184评论 0 1

友情链接更多精彩内容