要帮助小R计算能够获得的最大利润,我们可以使用动态规划的方法。由于交易存在冷冻期,我们需要跟踪三种状态:
- 持有股票状态(hold) :到第
i天为止,手上持有股票时的最大利润。 - 冻结状态(cooldown) :第
i天是卖出股票后的冷冻期,这天不能买入股票。 - 不持有股票且非冻结状态(rest) :到第
i天为止,手上不持有股票,并且不在冷冻期的最大利润。
以下是算法的具体步骤:
-
初始化:
hold[0] = -stocks[0]:第一天买入股票后的利润。cooldown[0] = 0:第一天不可能处于冷冻期。rest[0] = 0:第一天不做任何操作。
-
状态转移方程:
hold[i] = max(hold[i-1], rest[i-1] - stocks[i]):继续持有股票或者今天买入股票。cooldown[i] = hold[i-1] + stocks[i]:昨天持有股票,今天卖出进入冷冻期。rest[i] = max(rest[i-1], cooldown[i-1]):昨天是休息或者昨天是冷冻期,今天继续休息。
-
结果:
- 最后的最大利润是
max(rest[-1], cooldown[-1]),因为最后一天手上不应持有股票。
- 最后的最大利润是
下面是实现代码:
python
复制代码
def max_profit(stocks):
if not stocks:
return 0
n = len(stocks)
hold = [0] * n # 持有股票
rest = [0] * n # 休息状态
cooldown = [0] * n # 冷冻期
hold[0] = -stocks[0]
rest[0] = 0
cooldown[0] = 0
for i in range(1, n):
hold[i] = max(hold[i - 1], rest[i - 1] - stocks[i])
cooldown[i] = hold[i - 1] + stocks[i]
rest[i] = max(rest[i - 1], cooldown[i - 1])
return max(rest[-1], cooldown[-1])
# 测试样例
print(max_profit([1, 2])) # 输出:1
print(max_profit([2, 1])) # 输出:0
print(max_profit([1, 2, 3, 0, 2])) # 输出:3
print(max_profit([2, 3, 4, 5, 6, 7])) # 输出:5
print(max_profit([1, 6, 2, 7, 13, 2, 8])) # 输出:12
解释:
- 样例1:在第1天买入,第二天卖出,利润为
1。 - 样例2:股票价格下降,不进行任何交易,利润为
0。 - 样例3:在第1天买入,第3天卖出,利润为
2。然后在第4天休息(冷冻期),第5天再买入并卖出,累计利润为3。 - 样例4:每天价格上涨,买入后一直持有到最后一天卖出,利润为
5。 - 样例5:通过多次买卖,在遵守冷冻期规则的情况下,获得最大利润
12。
总结:
- 通过动态规划,我们有效地考虑了交易中的各种状态和规则。
- 这种方法的时间复杂度为
O(n),空间复杂度为O(n),其中n是股票价格列表的长度。