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

这题是FB最近的高频题,也是很经典的题目, 看到subarray的题目无非是dp或者two pointer的题目,但是这题看数组长度非常长,按普通区间DP或者3个pointer这种,复杂度为O(n^2),显然不合适。这题的解法充分利用了3个子数组这个条件,所以可以分开成左中右3个来考虑。用left[i]求0-i区间长度为k的最大和子数组的开始index,right[i] 求[i:len(nums)]区间内长度为k的最大和数组的开始index。之后我们针对中间数组,可以同步考虑左右边的情况,代码如下:

class Solution(object):
    def maxSumOfThreeSubarrays(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        # simplified version, left and right arrays have the same length with nums
        n = len(nums)
        if n < 3*k:
            return []
        presum = [0]
presum[j] - presum[i] = sum(nums[i:j])
for i in nums: presum.append(presum[-1]+i) # left[i], from 0-i, largest sum subarray of length k's start index left = [0] * n # right[i], from i-n, largest sum subarray of length k's start index right = [n-k] * n for i in xrange(k-1, n-2*k): if i == k-1: maxsum = presum[i+1] - presum[0] left[i] = 0 else: if presum[i+1] - presum[i-k+1] > maxsum: maxsum = presum[i+1] - presum[i-k+1] left[i] = i - k + 1 else: left[i] = left[i-1] for i in xrange(n-k, 2*k-1, -1): if i == n-k: maxsum = presum[n] - presum[n-k] right[i] = n - k else: if presum[i+k] - presum[i] > maxsum: maxsum = presum[i+k] - presum[i] right[i] = i else: right[i] = right[i+1] res = [] maxsum = 0 for i in xrange(k, n-2*k+1): l = left[i-1] r= right[i+k] if presum[i+k] - presum[i] + presum[l+k] - presum[l] + presum[r+k] - presum[r] > maxsum: maxsum = presum[i+k] - presum[i] + presum[l+k] - presum[l] + presum[r+k] - presum[r] res = [l, i, r] return res

注意这里为了方便left和right都取成了和nums一样的长度,但是只有其中一部分有意义。

posted on 2018-10-03 16:32  Sheryl Wang  阅读(105)  评论(0编辑  收藏  举报

导航