《Leetcode》309. 最佳买卖股票时机含冷冻期

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

示例:

输入: [1,2,3,0,2]
输出: 3 
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

1、题目分析

有三个状态:买入、卖出、冷冻。这种题目很显然都是利用动态规划方程来做,f(i),表示第i天后的最大收益。可以有三个状态变化:

  • 第i天后手持股票的最大收益dp[i][0]
  • 第i天后,没有股票,处于冷冻期的最大收益dp[i][1]
  • 第i天后,没有股票,也不在冷冻期的最大收益dp[i][2]

2、解题分析

  • 初始化起始状态
    • dp[i][0],dp[i][1],dp[i][2]  = -prices[0],0,0
  • 每个状态的动态转移方程
    • dp[i][0] = max(dp[i-1][0],dp[i][2]-prices[i])
    • dp[i][1] = dp[i-1][0]+prices[i]
    • dp[i][2] = max(dp[i-1][2],dp[i-1][1])
  • 最终结果
    • max(dp[n-1][0],dp[n-1][1],dp[n-1][2])
    • 但是由于最后一天持有股票是没有意义的,因此简化成max(dp[n-1][1],dp[n-1][2])

3、代码

class Solution:
    def maxProfit(self, prices: List[int]) -> int:

        #优化之前
        if not prices:
            return 0
        
        n = len(prices)
        # 表示第i天之后的累计收益
        # f[i][0]: 要么就是i-1天的时候的收益,第i天啥都不做;要么就是i-1天手上没有股票,不在冷冻期,第i天买了股票了
        # f[i][1]: 手上不持有股票,并且处于冷冻期中的累计最大收益
        # i天以后就处于冷冻期就说明i天进行卖出的操作了,然后就直接相加就可以
        # f[i][2]: 手上不持有股票,并且不在冷冻期中的累计最大收益
        # i天以后没有股票的收益其实就是i-1天没有股票的收益和i-1天后冷冻期的收益。

        #本来是res = max(f[i][0],f[i][1],f[i][2])
        #但是很显然n-1天后也就是最后一天后手持股票是没啥意义的,所以就变成了res = max(f[i][1],f[i][2])
        f = [[-prices[0], 0, 0]] + [[0] * 3 for _ in range(n - 1)]
        for i in range(1, n):
            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])

        # 优化后
        #因为f[i][0]只和f[i-1][0]有关系
        #因为f[i][1]只和f[i-1][0]有关系
        #因为f[i][2]只和f[i-1][2]和f[i-1][1]有关系
        #所以只需要保存这三个状态量就可以了,空间复杂度就降低到O(1)
        if not prices:
            return 0
        size = len(prices)
        f0, f1, f2 = -prices[0], 0, 0
        for i in range(1, size):
            newf0 = max(f0, f2 - prices[i])
            newf1 = f0 + prices[i]
            newf2 = max(f1, f2)
            f0, f1, f2 = newf0, newf1, newf2
        
        return max(f1, f2)

总结 股票问题早有耳闻,虽然知道用动态规划的方法,但是就是写不出来。动态规划太灵活了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值