1. 程式人生 > >[Swift]LeetCode188. 買賣股票的最佳時機 IV | Best Time to Buy and Sell Stock IV

[Swift]LeetCode188. 買賣股票的最佳時機 IV | Best Time to Buy and Sell Stock IV

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 個元素是一支給定的股票在第 天的價格。

設計一個演算法來計算你所能獲取的最大利潤。你最多可以完成 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 }