这是一道标准的动态规划题目,Leetcode上面也有类似的
题目理解
题目要求计算在给定股票价格序列中,通过多次买卖股票并遵守特定交易规则(卖出后存在一天的冷冻期)所能获得的最大利润。
数据结构选择
我们使用动态规划(Dynamic Programming, DP)来解决这个问题。具体来说,我们定义三个状态来表示每一天可能的交易状态:
- 买入状态 (
f[i][0]):表示在第i天结束时,持有股票的最大利润。 - 卖出状态 (
f[i][1]):表示在第i天结束时,不持有股票且处于卖出状态的最大利润。 - 冷冻状态 (
f[i][2]):表示在第i天结束时,不持有股票且处于冷冻状态的最大利润。
算法步骤
-
初始化:
- 如果股票价格列表为空,直接返回利润为
0。 - 初始化一个二维数组
f,大小为n x 3,其中n是股票价格列表的长度。 - 第一天(
i=0)的买入状态利润为-stocks[0],因为买入股票会导致利润减少。
- 如果股票价格列表为空,直接返回利润为
-
状态转移:
- 对于每一天
i(从第二天开始):- 买入状态 (
f[i][0]):可以从前一天的买入状态保持不变,或者从前一天的冷冻状态买入股票。 - 卖出状态 (
f[i][1]):只能从前一天的买入状态卖出股票。 - 冷冻状态 (
f[i][2]):可以从前一天的卖出状态或冷冻状态转移过来。
- 买入状态 (
- 对于每一天
-
结果:
- 最终的最大利润是最后一天的卖出状态或冷冻状态中的最大值。
代码实现
def max(a, b):
return a if a > b else b
def solution(stocks: list[int]) -> int:
n = len(stocks)
if n == 0:
return 0
# f[i][0]: 处于买入状态的最大利润
# f[i][1]: 处于卖出状态的最大利润
# f[i][2]: 处于冷冻状态的最大利润
f = [[0] * 3 for _ in range(n)]
f[0][0】 = -stocks[0] # 第一天买入
for i in range(1, n):
f[i][0] = max(f[i-1][0], f[i-1][2] - stocks[i]) # 当前状态为买入
f[i][1] = f[i-1][0] + stocks[i] # 当前状态为卖出
f[i][2] = max(f[i-1][1], f[i-1][2]) # 当前状态为冷冻
return max(f[n-1][1], f[n-1][2]) # 返回最大利润
if __name__ == "__main__":
# You can add more test cases here
print(solution([1, 2]) == 1 )
print(solution([2, 1]) == 0 )
print(solution([1, 2, 3, 0, 2]) == 3 )
print(solution([2, 3, 4, 5, 6, 7]) == 5 )
print(solution([1, 6, 2, 7, 13, 2, 8]) == 12 )
总结
通过动态规划,我们能够有效地计算出在遵守交易规则的情况下所能获得的最大利润。代码中使用了三个状态来表示每一天的可能交易状态,并通过状态转移方程来更新每一天的状态,最终得到最大利润。