leetcode309买卖股票时机与含冷冻期

不含冷冻期,动态规划解法

可以不使用动态规划,但是含冷冻期的股票问题就需要了,所以先铺垫一下:
在这里插入图片描述

这里可以对每一天定义两个状态:
dp[i][0]: 表示第i天不持股的最大利益
dp[i][1]: 表示第i天持股的最大利益
定义状态的记号,方便理解
< :表示买入股票,当第i天之前(包括第i天)买入了股票,是持股的状态
> :表示卖出股票,当卖出股票时定义为不持股的状态
, :表示什么都不做

不持股的状态 :<,,,>,,,<,,,>,,, 可以由前一天不持股、前一天持股但是今天刚好卖出,这两种状态推出
前一天持股但是今天刚好卖出:dp[i-1][1] + prices[i]
前一天不持股:dp[i-1][0]
于是:dp[i][0] = max(dp[i-1][1] + prices[i], dp[i-1][0])
持股的状态:<,,,>,,,<,,,  可以由前一天也持股、前一天不持股,但今天刚好买入, 这两种状态推出
前一天也持股 :dp[i-1][1]
前一天不持股,但今天刚好买入:dp[i-1][0] - prices[i]
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])

# 定义边界,第0天的状态(初始状态)
dp[0][0] = 0 # 不持有
dp[0][1] = - prices[0] # 持有,最大利益为负

最终的代码如下:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        length = len(prices)
        if length == 0:
            return 0
        dp = [[0]*2 for _ in range(length)] # 初始化数组
        # 定义边界,第0天的状态(初始状态)
        dp[0][0] = 0 # 不持有
        dp[0][1] = -prices[0] # 持有
        for i in range(1,length):# price[1,length)
            dp[i][0] = max(dp[i-1][1] + prices[i], dp[i-1][0])
            dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
        return dp[length-1][0]

股票问题,含冷冻期,动态规划解法

在这里插入图片描述
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

定义状态与其中的状态转移是关键,
最容易想到的状态是:是否持有股票

定义状态的记号,方便理解
< :表示买入股票,当第i天之前(包括第i天)买入了股票,是持股的状态
> :表示卖出股票,当卖出股票时定义为不持股的状态
, :表示什么都不做
— :表示冷冻期

依然要定义两个状态,即持股与不持股,
但是对于不持股的状态要分成两种:
一种是:,,,<,,,>  : 这一种表示今天刚好卖出而不持股,这种状态不能推出明天买入而持股的状态
一种是:,,,<,,,>_,,   : 这一种表示今天没有卖出,并且也不持股,这种状态可以得到明天买入股票而持股的状态
由于上面的区别,所以需要将不持股的两种状态分开定义
对于持股的状态:
只有一种:,,,<,,,>_,,<,,,
因此需要定义三种状态:
,,,<,,,>_,,
dp[i][0]: 表示不持股的最大利益,而且今天也没有卖出,可以由前一天dp[i-1][0], dp[i-1][2]得来

,,,<,,,>_,,<,,,
dp[i][1]: 表示持股的最大利益,可以由前一天持股dp[i-1][1], dp[i-1][0] - prices[i] 得来

,,,<,,,>
dp[i][2]: 表示不持股,而且今天卖出的最大利益, 可以由dp[i-1][1] + price[i]得来

初始状态:
dp[0][0] = 0 # 可以定义为第0天不持股状态,这个状态是不可以推出第二天买入而持股的状态
dp[0][1] = -prices[0]
dp[0][2] = 0 # 可以定义为第0天买入又卖出的 不持股状态,这个状态是不可以推出第二天买入而持股的状态

以下是完整代码:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        length = len(prices)
        if length == 0:
            return 0
        dp = [ [0]*3 for _ in range(length) ]
        dp[0][0] = 0
        dp[0][1] = -prices[0]
        dp[0][2] = 0
        for i in range(1,length):
            dp[i][0] = max(dp[i-1][0], dp[i-1][2]) # 不持有状态, 可有dp[i-1][2]以及dp[i-1][0] 得到
            dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i]) # 持有股票的状态,可由 dp[i-1][2]以及dp[i-1][1]得到
            dp[i][2] = dp[i-1][1]+prices[i] # 不持有,当天卖出的状态,可由dp[i-1][1] +prices[i] 得到
            # print(dp)
        return max(dp[length-1][0], dp[length-1][2])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值