代码随想录算法训练营第五十天| 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费

文档讲解:代码随想录

视频讲解:代码随想录B站账号

状态:看了视频题解和文章解析后做出来了

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

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n = len(prices)
        if n < 2:
            return 0

        dp = [[0]*3 for _ in range(len(prices))]
        dp[0][0] = -prices[0]

        for i in range(1, len(prices)):
            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][2], dp[i-1][1])

        return max(dp[-1][1], dp[-1][2])
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

1. 确定dp数组以及下标的含义

这道题引入了冷冻期的概念,也就是卖出以后有一天不能交易。

这里需要定义三个状态:

(1)状态0:持有股票

(2)状态1:不持有股票且进入冷冻期

(3)状态2:不持有股票且不在冷冻期

代码随想录算法训练营第五十天| 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费_第1张图片

2. 确定递推公式

- 状态0的持有股票有两种情况,第一种是延续昨天持有的状态,第二种是今天买了股票:

dp[i][0] = max(dp[i-1][0], dp[i-1][2] - prices[i]),注意买股票沿用的昨天不在冷冻期的状态,如果昨天进入了冷冻期那今天就不能买股票了。

- 状态1只有一种情况,也就是昨天持有股票今天卖了并进入冷冻期

dp[i][1] = dp[i-1][0] + prices[i]

- 状态2有两种情况,延续之前的不持有股票状态和刚从冷冻期解冻且不买股票。

dp[i][2] = max(dp[i-1][1], dp[i-1][2])

3. dp数组的初始化

只有状态0需要初始化为-prices[i],因为状态0是第一天就持有股票。

4. 遍历顺序

递推公式中有i-1,所以从前往后遍历

5. dp数组举例

代码随想录算法训练营第五十天| 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费_第2张图片

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

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

        for i in range(1, len(prices)):
            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 dp[-1][1]
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

和最常规的买卖股票题的唯一区别就是加了一个手续费,只有在卖出的时候减去手续费fee即可。

唯一差别在于递推公式部分,所以本篇也就不按照动规五部曲详细讲解了,主要讲解一下递推公式部分。

这里重申一下dp数组的含义:

dp[i][0] 表示第i天持有股票所省最多现金。 dp[i][1] 表示第i天不持有股票所得最多现金

如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来

  • 第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0]
  • 第i天买入股票,所得现金就是昨天不持有股票的所得现金减去 今天的股票价格 即:dp[i - 1][1] - prices[i]

所以:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);

在来看看如果第i天不持有股票即dp[i][1]的情况, 依然可以由两个状态推出来

  • 第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]
  • 第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金,注意这里需要有手续费了即:dp[i - 1][0] + prices[i] - fee

所以:dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);

最后返回的是最后一天不持有股票时候的现金数。

 

你可能感兴趣的:(算法,leetcode,职场和发展)