zoukankan      html  css  js  c++  java
  • 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一样的长度,但是只有其中一部分有意义。

  • 相关阅读:
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale
    CodeForces 785B Anton and Classes
    CodeForces 785A Anton and Polyhedrons
    爱奇艺全国高校算法大赛初赛C
    爱奇艺全国高校算法大赛初赛B
    爱奇艺全国高校算法大赛初赛A
    EOJ 3265 七巧板
    EOJ 3256 拼音魔法
    EOJ 3262 黑心啤酒厂
  • 原文地址:https://www.cnblogs.com/sherylwang/p/9740066.html
Copyright © 2011-2022 走看看