动态规划
- 我们假设
f[i]表示第i天结束后的累计最大收益,在这一天我们会有3种状态, - 持有股票——我们记为
f[i][0] - 不持有股票且冻结——我们记为
f[i][1] - 不持有股票但不冻结——我们记为
f[i][2]
状态转移式:
f[i][0]=max(f[i−1][0],f[i−1][2]−prices[i])
f[i][1]=f[i−1][0]+prices[i]
f[i][2]=max(f[i−1][1],f[i−1][2])
最终答案则是最后一天三种状态中的最大值,当然因为最后一天持有股票完全没有意义,因为不能卖故不可能比后两种状态值大,所以直接比较后两种状态即可max(f[n−1][1],f[n−1][2])
最后初始化边界条件
f[0][0] = -prices[0]
f[0][1] = 0
f[0][2] = 0
代码1:
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
n := len(prices)
// f[i][0]: 手上持有股票的最大收益
// f[i][1]: 手上不持有股票,并且处于冷冻期中的累计最大收益
// f[i][2]: 手上不持有股票,并且不在冷冻期中的累计最大收益
f := make([][3]int, n)
f[0][0] = -prices[0]
for i := 1; i < n; i++ {
f[i][0] = max(f[i-1][0], f[i-1][2] - prices[i])
f[i][1] = f[i-1][0] + prices[i]
f[i][2] = max(f[i-1][1], f[i-1][2])
}
return max(f[n-1][1], f[n-1][2])
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
代码2:
相对于代码1进行了内存优化,因为这一层的dp只需要上一层的dp元素就行了,所以没有必要建立完整的dp数组
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
n := len(prices)
f0, f1, f2 := -prices[0], 0, 0
for i := 1; i < n; i++ {
newf0 := max(f0, f2 - prices[i])
newf1 := f0 + prices[i]
newf2 := max(f1, f2)
f0, f1, f2 = newf0, newf1, newf2
}
return max(f1, f2)
}
func max(x, y int) int {
if x > y {
return x
}
return y
}