zoukankan      html  css  js  c++  java
  • [Swift]LeetCode689. 三个无重叠子数组的最大和 | Maximum Sum of 3 Non-Overlapping Subarrays

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址: https://www.cnblogs.com/strengthen/p/10501552.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

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

    给定数组 nums 由正整数组成,找到三个互不重叠的子数组的最大和。

    每个子数组的长度为k,我们要使这3*k个项的和最大化。

    返回每个区间起始索引的列表(索引从 0 开始)。如果有多个结果,返回字典序最小的一个。

    示例:

    输入: [1,2,1,2,6,7,5,1], 2
    输出: [0, 3, 5]
    解释: 子数组 [1, 2], [2, 6], [7, 5] 对应的起始索引为 [0, 3, 5]。
    我们也可以取 [2, 1], 但是结果 [1, 3, 5] 在字典序上更大。
    

    注意:

    • nums.length的范围在[1, 20000]之间。
    • nums[i]的范围在[1, 65535]之间。
    • k的范围在[1, floor(nums.length / 3)]之间。

    Runtime: 216 ms
    Memory Usage: 18.8 MB
     1 class Solution {
     2     func maxSumOfThreeSubarrays(_ nums: [Int], _ k: Int) -> [Int] {
     3         var n:Int = nums.count
     4         var mx:Int = Int.min
     5         var sums:[Int] = [0]
     6         var res:[Int] = [Int]()
     7         var left:[Int] = [Int](repeating:0,count:n)
     8         var right:[Int] = [Int](repeating:n - k,count:n)
     9         for num in nums
    10         {
    11             sums.append(sums.last! + num)       
    12         }
    13         var total:Int = sums[k] - sums[0]
    14         for i in k..<n
    15         {
    16             if sums[i + 1] - sums[i + 1 - k] > total
    17             {
    18                 left[i] = i + 1 - k
    19                 total = sums[i + 1] - sums[i + 1 - k]
    20             }
    21             else
    22             {
    23                 left[i] = left[i - 1]
    24             }
    25         }
    26         total = sums[n] - sums[n - k]
    27         for i in stride(from:n - 1 - k,through:0,by:-1)
    28         {
    29             if sums[i + k] - sums[i] >= total
    30             {
    31                 right[i] = i
    32                 total = sums[i + k] - sums[i]
    33             }
    34             else
    35             {
    36                 right[i] = right[i + 1]
    37             }
    38         }
    39         for i in k...(n - 2 * k)
    40         {
    41             var l:Int = left[i - 1]
    42             var r:Int = right[i + k]
    43             var total:Int = (sums[i + k] - sums[i]) + (sums[l + k] - sums[l]) + (sums[r + k] - sums[r])
    44             if mx < total
    45             {
    46                 mx = total
    47                 res = [l, i, r]
    48             }
    49         }   
    50         return res
    51     }
    52 }

    220ms

     1 class Solution {
     2     func maxSumOfThreeSubarrays(_ nums: [Int], _ k: Int) -> [Int] {
     3         if nums.count < 3 * k { return [Int]() }
     4 
     5         var sums = Array(repeating: 0, count: nums.count - k + 1)
     6         var s = nums[0..<k].reduce(0, +)
     7         sums[0] = s
     8         for i in 1..<sums.count {
     9             s = s - nums[i - 1] + nums[i + k - 1]
    10             sums[i] = s
    11         }
    12         
    13         var maxFrom = Array(repeating: 0, count: nums.count - k + 1)
    14         var idx = maxFrom.count - 1
    15         for i in (0..<maxFrom.count).reversed() {
    16             if sums[i] >= sums[idx] {
    17                 idx = i
    18             }
    19             maxFrom[i] = idx
    20         }
    21         
    22         var max2From = Array(repeating: (0, 0), count: nums.count - 2 * k + 1)
    23         var m = 0
    24         for i in (k..<max2From.count).reversed() {
    25             let j = maxFrom[i + k]
    26             let s = sums[i] + sums[j]
    27             if s >= m {
    28                 m = s
    29                 max2From[i] = (i, j)
    30             } else {
    31                 max2From[i] = max2From[i + 1]
    32             }
    33         }
    34         
    35         m = 0
    36         var res = [0, 0, 0]
    37         for i in 0..<max2From.count - k {
    38             let (x, y) = max2From[i + k]
    39             let s = sums[i] + sums[x] + sums[y]
    40             if m < s {
    41                 m = s
    42                 res = [i, x, y]
    43             }
    44         }
    45         return res
    46     }
    47 }

    228ms

     1 class Solution {
     2     
     3     func maxSumOfThreeSubarrays(_ nums: [Int], _ k: Int, _ debugMode: Bool = false) -> [Int] {
     4         guard nums.count > 1 && k <= (nums.count / 3) else {
     5             return [0]
     6         }
     7 
     8         // find the cumulative sum for window of size k
     9         let n = nums.count
    10 
    11         // compute the cumulative sum from the left
    12         let leftSum = self.leftSum(nums, k)
    13         if debugMode {
    14             print("leftSum: (leftSum)")
    15         }
    16 
    17         // holds the index in the leftSum array that has the maximum value seen so far from left
    18         let maxSumLeftIndex = self.maxSumLeftIndex(leftSum)
    19         if debugMode {
    20             print("maxSumLeftIndex: (maxSumLeftIndex)")
    21         }
    22 
    23         // holds the index in the rightSum array that has the maximum value seen so far from right
    24         let maxSumRightIndex = self.maxSumRightIndex(leftSum)
    25         if debugMode {
    26             print("maxSumRightIndex: (maxSumRightIndex)")
    27         }
    28 
    29         // find the triplet which has sum is maximum
    30         var result: [Int] = [0, 0, 0]
    31         var maxSum = Int.min
    32         for i in (2 * k - 1)..<(n - k) {
    33             let index1 = maxSumLeftIndex[i - k]
    34             let index2 = i
    35             let index3 = maxSumRightIndex[i + k]
    36             
    37             let sum1 = leftSum[index1]
    38             let sum2 = leftSum[index2]
    39             let sum3 = leftSum[index3]
    40 
    41             let sum = sum1 + sum2 + sum3
    42             if maxSum < sum {
    43                 maxSum = sum
    44                 result[0] = index1 - k + 1
    45                 result[1] = index2 - k + 1
    46                 result[2] = index3 - k + 1
    47             }
    48         }
    49 
    50         return result
    51     }
    52 
    53     // compute the cumulative sum from the left
    54     func leftSum(_ nums: [Int], _ k: Int) -> [Int] {
    55         let n = nums.count
    56         var leftSum = Array(repeating: 0, count: n)
    57         var leftRunningSum = (0..<k).reduce(0) { $0 + nums[$1] }
    58         leftSum[k-1] = leftRunningSum
    59         for i in k..<n {
    60             leftRunningSum -= nums[i-k]
    61             leftRunningSum += nums[i]
    62             leftSum[i] = leftRunningSum
    63         }
    64 
    65         return leftSum
    66     }
    67 
    68     // holds the index in the leftSum array that has the maximum value seen so far from left
    69     func maxSumLeftIndex(_ leftSum: [Int]) -> [Int] {
    70         let n = leftSum.count
    71         var maxSumLeftIndex = Array(repeating: 0, count: n)
    72         maxSumLeftIndex[0] = 0
    73         for i in 1..<n {
    74             if leftSum[i] > leftSum[maxSumLeftIndex[i-1]] {
    75                 maxSumLeftIndex[i] = i
    76             } else {
    77                 maxSumLeftIndex[i] = maxSumLeftIndex[i-1]
    78             }
    79         }
    80 
    81         return maxSumLeftIndex
    82     }
    83 
    84     // holds the index in the rightSum array that has the maximum value seen so far from right
    85     func maxSumRightIndex(_ rightSum: [Int]) -> [Int] {
    86         let n = rightSum.count
    87         var maxSumRightIndex = Array(repeating: 0, count: n)
    88         
    89         maxSumRightIndex[n - 1] = n - 1
    90         for i in (0..<(n-1)).reversed() {
    91             if rightSum[i] > rightSum[maxSumRightIndex[i+1]] {
    92                 maxSumRightIndex[i] = i
    93             } else {
    94                 maxSumRightIndex[i] = maxSumRightIndex[i+1]
    95             }
    96         }
    97         return maxSumRightIndex
    98     }    
    99 }

    244ms

     1 class Solution {
     2     func maxSumOfThreeSubarrays(_ nums: [Int], _ k: Int) -> [Int] {
     3         if nums.count < k*3 {
     4             return []
     5         }
     6         
     7         var sum = [Int](repeating: 0, count: nums.count)
     8         sum[0] = nums[0]
     9         for i in 1..<nums.count {
    10             sum[i] = nums[i] + sum[i-1]
    11         }
    12         
    13         var dp = [[Int]](repeating: [Int](repeating: 0, count: nums.count), count: 3)
    14         var prev = [[Int]](repeating: [Int](repeating: 0, count: nums.count), count: 2)
    15 
    16         for i in k-1..<nums.count {
    17             dp[0][i] = sum[i]
    18             if i >= k {
    19                 dp[0][i] -= sum[i-k]
    20             }
    21         }
    22         
    23         
    24         var maxSum = Int.min
    25         var maxIndex = -1
    26         for i in 1...2 {
    27             var maxPrevSum = Int.min
    28             var maxPrevIndex = -1
    29 
    30             for j in k*(i+1)-1..<nums.count {
    31                 if dp[i-1][j-k] > maxPrevSum {
    32                     maxPrevSum = dp[i-1][j-k]
    33                     maxPrevIndex = j-k
    34                 }
    35                 prev[i-1][j] = maxPrevIndex
    36                 dp[i][j] = maxPrevSum + sum[j] - sum[j-k]
    37                 
    38                 if i == 2 && dp[i][j] > maxSum {
    39                     maxSum = dp[i][j]
    40                     maxIndex = j
    41                 }
    42             }
    43             
    44         }
    45         
    46         let second = prev[1][maxIndex]
    47         let first = prev[0][second]
    48         return [first-k+1, second-k+1, maxIndex-k+1]
    49     }
    50 }

    256ms

     1 class Solution {
     2     func maxSumOfThreeSubarrays(_ nums: [Int], _ k: Int) -> [Int] {
     3         // calculate array of k-size subarrays sums
     4         var sumArray = [Int](repeating: 0, count: nums.count - k + 1)
     5         var num = 0
     6         for i in 0..<k {
     7             num += nums[i]
     8         }
     9         sumArray[0] = num
    10         for i in 1..<sumArray.count {
    11             num -= nums[i - 1]
    12             num += nums[i - 1 + k]
    13             sumArray[i] = num
    14         }
    15         //print(sumArray)
    16         var leftArr = [Int](repeating: 0, count: sumArray.count)
    17         var best = 0
    18         for i in 0..<sumArray.count {
    19             if sumArray[i] > sumArray[best] { best = i }
    20             leftArr[i] = best
    21         }
    22         //print(leftArr)
    23         var rightArr = [Int](repeating: 0, count: sumArray.count)
    24         best = sumArray.count - 1
    25         for i in stride(from: sumArray.count - 1, through: 0, by: -1) {
    26             if sumArray[i] >= sumArray[best] { best = i }
    27             rightArr[i] = best
    28         }
    29         //print(rightArr)
    30         var res = [-1, -1, -1]
    31         for j in k..<sumArray.count - k {
    32             let i = leftArr[j - k]
    33             let k = rightArr[j + k]
    34             let sum = sumArray[i] + sumArray[j] + sumArray[k]
    35             if res[0] == -1 || sum > res.map({ sumArray[$0] }).reduce(0, +) {
    36                 res[0] = i
    37                 res[1] = j
    38                 res[2] = k
    39             }
    40         }
    41         return res
    42     }
    43 }

    356ms

     1 class Solution {
     2     struct Result: Comparable {
     3         let sum: Int
     4         let indicies: [Int]
     5         
     6         static func < (lhs: Result, rhs: Result) -> Bool {
     7             return lhs.sum < rhs.sum
     8         }
     9     }
    10     func maxSumOfThreeSubarrays(_ nums: [Int], _ k: Int) -> [Int] {
    11         var sum: [[Result]] = Array(repeating: Array(repeating: Result(sum: 0, indicies: []), count: nums.count), count: 4)
    12         var kNumsSum = 0
    13         for i in stride(from: nums.count - 1, through: 0, by: -1) {
    14             kNumsSum += nums[i]
    15             if i <= nums.count - k {
    16                 if i < nums.count - k {
    17                     kNumsSum -= nums[i + k]
    18                 }
    19                 sum[1][i] = Result(sum: kNumsSum, indicies: [i])
    20             }
    21         }
    22         var maxResult = Result(sum: 0, indicies: [])
    23         for j in 2...3 {
    24             for i in ((j - 1) * k)...(nums.count - k) {
    25                 let prevMaxSum = sum[j][i - 1].sum - sum[1][i - 1].sum
    26                 var prevIndices = sum[j][i - 1].indicies
    27                 if prevIndices.count > 0 {
    28                     prevIndices.removeLast()
    29                 }
    30                 var result = Result(sum: prevMaxSum, indicies: prevIndices)
    31                 if sum[j - 1][i - k].sum > prevMaxSum {
    32                     result = sum[j - 1][i - k]
    33                 }
    34                 
    35                 sum[j][i] = Result(sum: result.sum + sum[1][i].sum, 
    36                                    indicies: result.indicies + [i])
    37                 if j == 3 && maxResult < sum[j][i] {
    38                     maxResult = sum[j][i]
    39                 }
    40             }
    41         }
    42         return maxResult.indicies
    43     }
    44 }

    396ms

     1 class Solution {
     2     struct Result: Comparable {
     3         let sum: Int
     4         let indicies: [Int]
     5         
     6         static func < (lhs: Result, rhs: Result) -> Bool {
     7             return lhs.sum < rhs.sum
     8         }
     9         
    10         static func + (lhs: Result, rhs: Result) -> Result {
    11             return Result(sum: lhs.sum + rhs.sum, indicies: lhs.indicies + rhs.indicies)
    12         }
    13     }
    14     func maxSumOfThreeSubarrays(_ nums: [Int], _ k: Int) -> [Int] {
    15         let zeroResult = Result(sum: 0, indicies: [])
    16         var maxSum: [[Result]] = Array(repeating: Array(repeating: zeroResult, count: 4), count: nums.count)
    17         
    18         var sum: [Int] = Array(repeating: 0, count: nums.count)
    19         var kNumsSum = 0
    20         
    21         for i in stride(from: nums.count - 1, through: 0, by: -1) {
    22             kNumsSum += nums[i]
    23             if i < nums.count - k {
    24                 kNumsSum -= nums[i + k]
    25             }
    26             sum[i] = kNumsSum
    27         }
    28         
    29         for j in 1...3 {
    30             for i in (j * k - 1)..<nums.count {
    31                 var maxResult = zeroResult
    32                 if i >= k {
    33                     maxResult = maxSum[i - k][j - 1]
    34                 }
    35                 let lastSubArrayIndex = i - k + 1
    36                 maxResult = Result(sum: maxResult.sum + sum[lastSubArrayIndex], 
    37                                    indicies: maxResult.indicies + [lastSubArrayIndex])
    38                 if i > 0 && maxSum[i - 1][j] >= maxResult {
    39                     maxResult = maxSum[i - 1][j]
    40                 }
    41                 maxSum[i][j] = maxResult
    42             }
    43         }
    44         return maxSum[nums.count - 1][3].indicies
    45     }
    46 }
  • 相关阅读:
    简版一致性hash算法实现
    js类型转换问题
    VIVADO 2017.4配置MIG IP注意事项
    工作笔记2
    工作笔记1
    spring5 + hibernate5(redisson二级缓存) + JPA + JTA + ActiveMQ(JMS)
    spring data jpa 缓存(hibernate)
    JPA @Temporal
    C++ RTTI
    二叉树遍历方法总结
  • 原文地址:https://www.cnblogs.com/strengthen/p/10501552.html
Copyright © 2011-2022 走看看