122-买卖股票的最佳时机 II
题目
买卖无数次
给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
思路
- 以某个价格为基准,遍历天数,会遇到两种可能,由于我们只能买卖无数次,因此对于这两种操作如下:
- 比当前大,那么就计算收益,同时更新最小值及下次收益;
- 比当前小,那么买最小的呀;
解法一
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
res, min := 0, prices[0]
for i := 1; i < len(prices); i++ {
if prices[i] < min {
min = prices[i]
} else {
res += prices[i] - min
min = prices[i]
}
}
return res
}
解法二
func maxProfit(prices []int) int {
buy, sell := math.MaxInt32, math.MinInt32
res := 0 // 总收益
for i := 0; i < len(prices); i++ {
buy = min(buy, prices[i]) // 可以理解为两次交易之间的股票最小值
sell = max(sell, prices[i] - buy) // 一次交易的收益
// sell > 0 表示完成一次买卖,所以更新buy;
if sell > 0 {
res += sell
buy = prices[i]
sell = 0
}
}
return res
}
func max(a, b int) int {
if a < b {
return b
}
return a
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
解法三
- 初始值:第1天,不持有股票,收益为0;持有股票,收益为
-prices[0]
; - 状态变量:天数,是否持有股票;
- 备忘录矩阵:
dp[i][j]
,i
表示天数,j
表示是否持有股票,0表示不持有,1表示持有; - 决策:
- 第
i
天持有股票 =max
(第i-1
天无交易, 第i-1
天买入股票) - 第
i
天不持有股票 =max
(第i-1
天无交易,第i-1
天卖出股票)
- 第
func maxProfit(prices []int) int {
dp := make([][2]int, len(prices))
dp[0][0] = 0
dp[0][1] = -prices[0]
for i := 1; i < len(prices); i++ {
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
}
return dp[len(prices) - 1][0]
}
func max(a, b int) int {
if a < b {
return b
}
return a
}
B站视频
兄弟们,一起来刷题啊!!! 股票问题B站视频链接
总结
dp[i][0][k] = max(dp[i-1][0][k] (无交易) + dp[i][1][k-1] + prices[i] (卖出))
dp[i][1][k] = max(dp[i-1][1][k] (无交易) + dp[i][0][k] - prices[i] (买入))
只要明白这个状态转移方程,这类问题就非常丝滑啦;