代码随想录算法训练营第五十天 | 动态规划 part 11 | 买卖股票iii、iv

目录

  • 123.买卖股票的最佳时机III
    • 思路
    • 代码
  • 188.买卖股票的最佳时机IV
    • 思路
    • 代码

123.买卖股票的最佳时机III

Leetcode

代码随想录算法训练营第五十天 | 动态规划 part 11 | 买卖股票iii、iv_第1张图片

思路

  • dp数组含义:这道题和之前的买卖股票不同的地方在于,最多可以完成两笔交易。所以对于第i天可以有以下的四种状态:

    1. 没有操作
    2. 第一次持有股票
    3. 第一次不持有股票
    4. 第二次持有股票
    5. 第二次不持有股票

    dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。

    需要注意:dp[i][1],表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票。

  • 递推公式:

    • dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i])
    • dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i])
    • dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i])
    • dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i])
  • 初始化:第一次买入、第二次买入初始化为-prices[0],第二次买入相当于第一天内买入卖出再买入了。只有这样初始化才能方便后面的推导。

  • 遍历顺序:从前往后

  • 举例推导
    代码随想录算法训练营第五十天 | 动态规划 part 11 | 买卖股票iii、iv_第2张图片

代码

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        dp = [[0] * 5 for _ in range(len(prices))]
        dp[0][1] = -prices[0]
        dp[0][3] = -prices[0]

        for i in range(1, len(prices)):
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i])
            dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i])
            dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i])
            dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i])
        
        return dp[-1][4]
  • 时间复杂度:O(n)
  • 空间复杂度:O(n × 5)

188.买卖股票的最佳时机IV

Leetcode

代码随想录算法训练营第五十天 | 动态规划 part 11 | 买卖股票iii、iv_第3张图片

思路

这题是上一题的超级加倍版本,要求最多可以有k笔交易。

总结地来说,如果最多有可以k笔交易,那么我们需要设2k个状态。参考上一题,最多两笔交易,我们有4个状态(不包括0操作)。

在每天的买入和卖出的状态中,j为奇数则为买入,j为偶数则为卖出。

代码

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        dp = [[0] * (2 * k + 1) for _ in range(len(prices))]
        for i in range(1, k+1):
        	# 为买入的状态做初始化
            dp[0][2 * i - 1] = -prices[0]
        
        for i in range(1,len(prices)):
            for j in range(1, k + 1):
            	# 奇数买入
                dp[i][2*j-1] = max(dp[i-1][2*j-1], dp[i-1][2*j-2] - prices[i])
                # 偶数卖出
                dp[i][2*j] = max(dp[i-1][2*j], dp[i-1][2*j-1] + prices[i])
        
        return dp[-1][-1]

  • 时间复杂度: O(n * k),其中 n 为 prices 的长度
  • 空间复杂度: O(n * k)

你可能感兴趣的:(代码随想录算法训练营,算法,动态规划,python,leetcode)