算法记录 | Day51 动态规划

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

思路:

1.确定dp数组以及下标的含义:dp[i][j] ,表示为:第 i 天第 j 种情况(0 <= j <= 2)下,所获取的最大利润。

对于每一天结束时的状态总共有以下几种:

  • 买入状态:
    • 今日买入
    • 之前买入,之后一直持有无操作
  • 卖出状态:
    • 今日买出,正处于冷冻期
    • 昨天卖出,今天结束后度过了冷冻期
    • 之前卖出,度过了冷冻期后无操作

在买入状态中,今日买入和之前买入的状态其实可以看做是股票的持有状态,可以将其合并为一种状态。

在卖出状态中,昨天卖出和之前卖出的状态其实可以看做是无股票并度过了冷冻期状态,可以将其合并为一种状态。

这样总结下来可以划分为三个状态:

  • 股票的持有状态。
  • 无股票,并且处于冷冻期状态。
  • 无股票,并且不处于冷冻期状态

2.确定状态转移公式:

  • 第0种状态(股票的持有状态)下可以有两种状态推出,取最大的那一种赋值:
    • 昨天就已经持有的:dp[i][0] = dp[i - 1][0]
    • 今天刚买入的(则昨天不能持有股票也不能处于冷冻期,应来自于前天卖出状态):dp[i][0] = dp[i - 1][2] - prices[i]
  • 第1种状态(无股票,并且处于冷冻期状态)下可以有一种状态推出:
    • 今天卖出:dp[i] = dp[i - 1][0] + prices[i]
  • 第2种状态(无股票,并且不处于冷冻期状态)下可以有两种状态推出,取最大的那一种赋值:
    • 昨天卖出:dp[i] = dp[i - 1][1]
    • 之前卖出:dp[i] = dp[i - 1][2]

3.初始化:

可以很明显看出第一天不做任何操作就是 dp[0][0] = 0,第一次买入就是 dp[0][1] = -prices[i]

第一次卖出的话,可以视作为没有盈利(当天买卖,价格没有变化),即 dp[0][2] = 0。第二次买入的话,就是 dp[0][3] = -prices[i]。同理第二次卖出就是 dp[0][4] = 0

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        size = len(prices)
        if size == 0:
            return 0
        dp = [[0 for _ in range(4)] for _ in range(size)]

        dp[0][0] = -prices[0]
        for i in range(1, size):
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i])
            dp[i][1] = dp[i - 1][0] + prices[i]
            dp[i][2] = max(dp[i - 1][1], dp[i - 1][2])
        return max(dp[size - 1][0], dp[size - 1][1], dp[size - 1][2])

714.买卖股票的最佳时机含手续费

本题和动态规划:122.买卖股票的最佳时机II (opens new window)的区别就是这里需要多一个减去手续费的操作

class Solution:
    def maxProfit(self, prices: List[int], fee: int) -> int:
        n = len(prices)
        dp = [[0] * 2 for _ in range(n)]
        dp[0][0] = -prices[0] #持股票
        for i in range(1, n):
            dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i])
            dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i] - fee)
        return max(dp[-1][0], dp[-1][1])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值