[Swift]LeetCode188. 買賣股票的最佳時機 IV | Best Time to Buy and Sell Stock IV
阿新 • • 發佈:2018-12-26
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most ktransactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
Example 1:
Input: [2,4,1], k = 2 Output: 2 Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.
Example 2:
Input: [3,2,6,5,0,3], k = 2 Output: 7 Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4. Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
給定一個數組,它的第 i 個元素是一支給定的股票在第 i 天的價格。
設計一個演算法來計算你所能獲取的最大利潤。你最多可以完成 k 筆交易。
注意: 你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。
示例 1:
輸入: [2,4,1], k = 2 輸出: 2 解釋: 在第 1 天 (股票價格 = 2) 的時候買入,在第 2 天 (股票價格 = 4) 的時候賣出,這筆交易所能獲得利潤 = 4-2 = 2 。
示例 2:
輸入: [3,2,6,5,0,3], k = 2 輸出: 7 解釋: 在第 2 天 (股票價格 = 2) 的時候買入,在第 3 天 (股票價格 = 6) 的時候賣出, 這筆交易所能獲得利潤 = 6-2 = 4 。 隨後,在第 5 天 (股票價格 = 0) 的時候買入,在第 6 天 (股票價格 = 3) 的時候賣出, 這筆交易所能獲得利潤 = 3-0 = 3 。
48ms
1 class Solution { 2 func maxProfit(_ k: Int, _ prices: [Int]) -> Int { 3 guard prices.count > 1, k > 0 else { return 0 } 4 let n = prices.count 5 6 if k >= (n / 2) { 7 var res = 0 8 for i in 1..<n { 9 if (prices[i] > prices[i-1]) { 10 res += prices[i] - prices[i-1] 11 } 12 13 } 14 return res 15 } 16 var mp = [[Int]](repeating: [Int](repeating: 0, count: k + 1), count: prices.count) 17 for i in 1...k { 18 var localMax = -prices[0] 19 for j in 1..<n { 20 mp[j][i] = max(mp[j-1][i], prices[j]+localMax) 21 localMax = max(localMax, mp[j-1][i-1]-prices[j]) 22 } 23 } 24 return mp[prices.count-1][k] 25 } 26 }
52ms
1 class Solution { 2 func maxProfit(_ k: Int, _ prices: [Int]) -> Int { 3 4 var n = prices.count 5 if n < 2 || k == 0 { return 0 } 6 if k >= n { return maxProfit(prices)} 7 var l = Array(repeating: 0, count: k+1) 8 var g = Array(repeating: 0, count: k+1) 9 for i in 0..<n-1 { 10 var diff = prices[i+1] - prices[i] 11 for j in stride(from: k, through: 1, by: -1){ 12 l[j] = max(g[j-1] + max(diff, 0), l[j] + diff) 13 g[j] = max(g[j], l[j]) 14 } 15 } 16 17 18 return g[k]; 19 20 } 21 func maxProfit(_ prices: [Int]) -> Int { 22 var res = 0 23 for i in 1..<prices.count { 24 res += max(0, prices[i] - prices[i-1]) 25 } 26 return res 27 } 28 }
120ms
1 class Solution { 2 func maxProfit(_ k: Int, _ prices: [Int]) -> Int { 3 if k == 0 || prices.count < 2 { 4 return 0 5 } 6 7 let count = prices.count 8 if count <= k * 2 + 1 { 9 return maxProfitUn(prices) 10 } 11 12 if k == 2 { 13 return maxProfitTwo(prices) 14 } 15 16 var mustSell = Array(repeating: Array(repeating: 0 , count: k+1), count: count) 17 var globalSell = Array(repeating: Array(repeating: 0, count: k+1), count: count) 18 19 for j in 1...k { 20 for i in 1..<count { 21 var profit = prices[i] - prices[i-1] 22 profit = max(profit, 0) 23 mustSell[i][j] = max(globalSell[i-1][j-1] + profit, mustSell[i-1][j] + prices[i] - prices[i-1]) 24 globalSell[i][j] = max(globalSell[i-1][j], mustSell[i][j]) 25 } 26 } 27 28 return globalSell[count-1][k] 29 } 30 31 func maxProfitUn(_ prices : [Int]) -> Int { 32 if prices.count < 2 { 33 return 0 34 } 35 36 let count = prices.count 37 var res = 0 38 for i in 1..<count { 39 if prices[i] > prices[i-1] { 40 res += prices[i] - prices[i-1] 41 } 42 } 43 44 return res 45 } 46 47 func maxProfitTwo(_ prices : [Int]) -> Int { 48 if prices.count < 2 { 49 return 0 50 } 51 52 let count = prices.count 53 54 var curMax = 0 55 56 var dp = Array(repeating: 0, count: count) 57 58 var curMin = prices[0] 59 for i in 1..<count { 60 curMax = max(curMax, prices[i] - curMin) 61 curMin = min(curMin, prices[i]) 62 dp[i] = curMax 63 } 64 65 var maxPrice = prices[count - 1] 66 curMax = 0 67 var dp2 = Array(repeating: 0, count: count) 68 for i in stride(from: count-1, to: -1, by: -1) { 69 curMax = max(curMax, maxPrice - prices[i]) 70 maxPrice = max(maxPrice, prices[i]) 71 dp2[i] = curMax 72 } 73 74 curMax = 0 75 for i in stride(from: count-1, to: 0, by: -1) { 76 curMax = max(curMax, dp[i] + dp2[i]) 77 } 78 79 return curMax 80 } 81 }
704ms
1 class Solution { 2 3 struct Section { 4 5 var start: Int 6 var end: Int 7 var hasProfit: Bool 8 var countedProfit: Int? 9 var countedStart: Int? 10 var countedEnd: Int? 11 var countedHasProfit: Bool? 12 13 init() { 14 self.start = 0 15 self.end = 0 16 self.hasProfit = false 17 } 18 19 init(start: Int, end: Int, hasProfit: Bool) { 20 21 self.start = start 22 self.end = end 23 self.hasProfit = hasProfit 24 } 25 } 26 27 func maxProfit(_ k: Int, _ prices: [Int]) -> Int { 28 29 if prices.count < 2 { 30 return 0 31 } 32 33 var totalProfit = 0 34 35 36 var subRange:[Section] = [] 37 38 subRange.append(Section.init(start: 0, end: prices.count-1, hasProfit: false)) 39 40 for _ in 0..<k { 41 42 var maxProfit = 0 43 var tmpProfit = 0 44 45 var maxIndex = -1 46 47 var maxSection = Section.init() 48 49 for index in 0..<subRange.count { 50 51 var tmpSection = Section.init() 52 53 if let countedProfit = subRange[index].countedProfit { 54 55 tmpProfit = countedProfit 56 57 tmpSection.start = subRange[index].countedStart! 58 tmpSection.end = subRange[index].countedEnd! 59 tmpSection.hasProfit = subRange[index].countedHasProfit! 60 61 } else { 62 if subRange[index].hasProfit { 63 64 tmpProfit = -findMin(prices, subRange[index].start, subRange[index].end, &tmpSection) 65 66 } else { 67 68 tmpProfit = findMax(prices, subRange[index].start, subRange[index].end, &tmpSection) 69 } 70 71 72 subRange[index].countedProfit = tmpProfit 73 subRange[index].countedStart = tmpSection.start 74 subRange[index].countedEnd = tmpSection.end 75 subRange[index].countedHasProfit = tmpSection.hasProfit 76 } 77 78 if maxProfit < tmpProfit { 79 80 maxProfit = tmpProfit 81 maxIndex = index 82 83 maxSection = tmpSection 84 } 85 } 86 87 if maxIndex < 0 { 88 89 break 90 } else { 91 92 let tmp = subRange[maxIndex] 93 94 95 maxSection.countedProfit = nil 96 maxSection.countedStart = nil 97 maxSection.countedEnd = nil 98 99 if tmp.hasProfit { 100 101 if maxSection.start > tmp.start { 102 subRange.append(Section.init(start: tmp.start, end:maxSection.start, hasProfit: true)) 103 } 104 105 if maxSection.end < tmp.end { 106 subRange.append(Section.init(start: maxSection.end, end: tmp.end, hasProfit: true)) 107 } 108 109 maxSection.start += 1 110 maxSection.end -= 1 111 112 if maxSection.start < maxSection.end { 113 subRange[maxIndex] = maxSection 114 } else { 115 subRange.remove(at: maxIndex) 116 } 117 118 119 } else { 120 121 if tmp.start < maxSection.start - 1 { 122 subRange.append(Section.init(start: tmp.start, end: maxSection.start - 1, hasProfit: false)) 123 } 124 125 if maxSection.end + 1 < tmp.end { 126 subRange.append(Section.init(start: maxSection.end + 1, end: tmp.end, hasProfit: false)) 127 } 128 129 subRange[maxIndex] = maxSection 130 131 } 132 133 totalProfit += maxProfit 134 135 } 136 137 } 138 139 return totalProfit 140 } 141 142 func findMax(_ prices: [Int], _ startFlag: Int, _ endFlag: Int, _ section: inout Section) -> Int { 143 144 if startFlag >= endFlag { 145 return 0 146 } 147 148 section.hasProfit = true 149 150 var tmpProfit = 0; 151 var tmpStartIndex = startFlag; 152 153 var total = 0 154 155 for i in startFlag...endFlag { 156 157 total = prices[i] - prices[tmpStartIndex] 158 159 if total < 0 { 160 tmpStartIndex = i 161 total = 0 162 163 } else { 164 165 if total > tmpProfit { 166 tmpProfit = total 167 section.end = i 168 section.start = tmpStartIndex 169 } 170 } 171 } 172 173 return tmpProfit 174 } 175 176 func findMin(_ prices: [Int], _ startFlag: Int, _ endFlag: Int, _ section: inout Section) -> Int { 177 178 if startFlag >= endFlag { 179 return 0 180 } 181 182 183 section.hasProfit = false 184 185 var tmpLoss = 0; 186 var tmpStartIndex = startFlag; 187 188 var total = 0 189 190 for i in startFlag...endFlag { 191 192 total = prices[i] - prices[tmpStartIndex] 193 194 if total > 0 { 195 tmpStartIndex = i 196 total = 0 197 198 } else { 199 200 if total < tmpLoss { 201 tmpLoss = total 202 section.end = i 203 section.start = tmpStartIndex 204 } 205 } 206 } 207 208 return tmpLoss 209 } 210 }
3464ms
1 class Solution { 2 3 class Section { 4 5 var start: Int 6 var end: Int 7 var hasProfit: Bool 8 9 10 init(start: Int, end: Int, hasProfit: Bool) { 11 12 self.start = start 13 self.end = end 14 self.hasProfit = hasProfit 15 } 16 } 17 18 func maxProfit(_ k: Int, _ prices: [Int]) -> Int { 19 20 if prices.count < 2 { 21 return 0 22 } 23 24 var totalProfit = 0 25 26 27 var subRange:[Section] = [] 28 29 subRange.append(Section.init(start: 0, end: prices.count-1, hasProfit: false)) 30 31 for _ in 0..<k { 32 33 34 var maxProfit = 0 35 var tmpProfit = 0 36 37 var maxSectionStart = 0 38 var maxSectionEnd = 0 39 40 var maxIndex = -1 41 42 for index in 0..<subRange.count { 43 44 var tmpReceive: (profit: Int, startIndex: Int, endIndex: Int) 45 46 47 if subRange[index].hasProfit { 48 tmpReceive = findMin(prices, subRange[index].start, subRange[index].end) 49 tmpProfit = -tmpReceive.profit 50 51 } else { 52 53 tmpReceive = findMax(prices, subRange[index].start, subRange[index].end) 54 tmpProfit = tmpReceive.profit 55 } 56 57 58 if maxProfit < tmpProfit { 59 60 maxProfit = tmpProfit 61 maxIndex = index 62 63 maxSectionStart = tmpReceive.startIndex 64 maxSectionEnd = tmpReceive.endIndex 65 66 } 67 } 68 69 if maxIndex < 0 { 70 71 break 72 } else { 73 74 let tmp = subRange[maxIndex] 75 76 77 if tmp.hasProfit { 78 79 subRange.append(Section.init(start: tmp.start, end: maxSectionStart, hasProfit: true)) 80 subRange.append(Section.init(start: maxSectionEnd, end: tmp.end, hasProfit: true)) 81 82 tmp.start = maxSectionStart + 1 83 tmp.end = maxSectionEnd - 1 84 tmp.hasProfit = false 85 // subRange[maxIndex] = tmp 86 87 } else { 88 89 90 subRange.append(Section.init(start: tmp.start, end: maxSectionStart - 1, hasProfit: false)) 91 subRange.append(Section.init(start: maxSectionEnd + 1, end: tmp.end, hasProfit: false)) 92 93 tmp.start = maxSectionStart 94 tmp.end = maxSectionEnd 95 tmp.hasProfit = true 96 // subRange[maxIndex] = tmp 97 98 } 99 100 totalProfit += maxProfit 101 102 } 103 104 } 105 106 return totalProfit 107 } 108 109 func findMax(_ prices: [Int], _ startFlag: Int, _ endFlag: Int) -> (profit: Int, startIndex: Int, endIndex: Int) { 110 111 if startFlag >= endFlag { 112 return (0, 0, 0) 113 } 114 115 var startIndex = 0 116 var endIndex = 0 117 118 var tmpProfit = 0; 119 var tmpStartIndex = startFlag; 120 121 var total = 0 122 123 for i in startFlag...endFlag { 124 125 total = prices[i] - prices[tmpStartIndex] 126 127 if total < 0 { 128 tmpStartIndex = i 129 total = 0 130 131 } else { 132 133 if total > tmpProfit { 134 tmpProfit = total 135 endIndex = i 136 startIndex = tmpStartIndex 137 } 138 } 139 } 140 141 return (tmpProfit, startIndex, endIndex) 142 } 143 144 func findMin(_ prices: [Int], _ startFlag: Int, _ endFlag: Int) -> (profit: Int, startIndex: Int, endIndex: Int) { 145 146 if startFlag >= endFlag { 147 return (0, 0, 0) 148 } 149 150 var startIndex = 0 151 var endIndex = 0 152 153 var tmpLoss = 0; 154 var tmpStartIndex = startFlag; 155 156 var total = 0 157 158 for i in startFlag...endFlag { 159 160 total = prices[i] - prices[tmpStartIndex] 161 162 if total > 0 { 163 tmpStartIndex = i 164 total = 0 165 166 } else { 167 168 if total < tmpLoss { 169 tmpLoss = total 170 endIndex = i 171 startIndex = tmpStartIndex 172 } 173 } 174 } 175 176 return (tmpLoss, startIndex, endIndex) 177 } 178 }