为有牺牲多壮志,敢教日月换新天。

[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 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

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 }

 

 

posted @ 2019-03-09 15:58  为敢技术  阅读(304)  评论(0编辑  收藏  举报