题目
给定股票价格数组,你可以多次交易,但卖出股票后第二天不能立刻再买入,问最大收益。
题目分析
这题不难想到“每天都做决策”,难的是状态不能只写成“买或不买”。
因为“刚卖出”这个状态会直接影响下一天是否允许买入,所以必须把状态拆细。
方法一:直觉解法
如果只用“持有 / 不持有”两个状态,冷冻期信息会丢失,转移很容易写错。
方法二:优化思路
更清晰的拆法是:
hold:当天结束时持有股票sold:当天刚卖出股票rest:当天结束时不持有且不在卖出当日
这样冷冻期就能自然表达出来。
Go 实现
1func maxProfit(prices []int) int {
2 if len(prices) == 0 {
3 return 0
4 }
5
6 hold := -prices[0]
7 sold := 0
8 rest := 0
9
10 for i := 1; i < len(prices); i++ {
11 prevHold, prevSold, prevRest := hold, sold, rest
12 hold = max(prevHold, prevRest-prices[i])
13 sold = prevHold + prices[i]
14 rest = max(prevRest, prevSold)
15 }
16
17 return max(sold, rest)
18}
19
20func max(a, b int) int {
21 if a > b {
22 return a
23 }
24 return b
25}
复杂度分析
- 时间复杂度:
O(n) - 空间复杂度:
O(1)
易错点
sold表示的是“当天刚卖出”,不是所有不持有状态hold的转移要从rest来,不能直接从sold来,因为冷冻期不允许次日买入
我的复盘
这题让我再次确认,动态规划里很多难点根本不在实现,而在状态设计。一旦状态拆得不够细,转移式就会看起来“差一点对”。