[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)]
之间。
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 }