day42 动态规划part09 买卖股票-下

76 阅读3分钟

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

文章讲解

最多完成k笔交易,参考2笔交易的,状态需要2k+1。

思路:

需要准备2k+1的dp表,0表示不操作,奇数表示买入,偶数表示卖出。
class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        if not prices:
            return 0
        n = len(prices)
        dp = [[0] * (2*k+1) for _ in range(n)]

        # 初始化:第0天的奇数初始化为-prices[0],索引范围是0-2k,其中1-2k-1是奇数
        for i in range(1, 2*k, 2):
            dp[0][i] = -prices[0]

        # 迭代行
        for i in range(1, n):
            # 迭代列,两两一组 j+1=1,j从0开始,j+2<=2k j<=2k-2 j<2k-1
            for j in range(0,2*k-1 ,2): # 索引范围0-2k,从0开始,每次+2,最大取到2k,但是j需要j+1 j+2,j最大为2k-2,范围是[0,2k-1]
                dp[i][j+1] = max(dp[i-1][j+1], dp[i-1][j] - prices[i])
                dp[i][j+2] = max(dp[i-1][j+2], dp[i-1][j+1] + prices[i])
        return dp[-1][-1]

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

文章讲解

卖出之后需要隔开一天再买。

思路:

四个状态,1 持有股票 ,把不持有股票拆分成三种状态: 2 保持卖出(冷冻期后若干天) 3 具体卖出股票(冷冻期前一天) 4 冷冻期(卖出后一天)

卖出2 冷冻期4 保持卖出 保持卖出...

1 持有股票(买进):前一天持有dp[i-1][0],前一天保持卖出或者冷冻期,dp[i-1][3]-prices[i] dp[i-1][1]-prices[i]
2 保持卖出:两种情况,前一天保持卖出或者冷冻期,dp[i-1][2] dp[i-1][3]
3 卖出:前一天必须要持有,dp[i-1][0] + prices[i]
4 冷冻期:前一天必须要卖出,dp[i-1][2]
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0
        n = len(prices)

        # 初始化
        dp = [[0] * 4 for _ in range(n)]
        dp[0][0] = - prices[0]
        
        # 0:持有 1:保持卖出 2:卖出 3:冷冻期 (1-3都是不持有状态)
        for i in range(1, n):
            dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i], dp[i-1][3]- prices[i]) # 持有:前一天持有,前一天冷冻或者保持卖出可以再买
            dp[i][1] = max(dp[i-1][3], dp[i-1][1]) # 保持卖出: 冷冻、保持卖出
            dp[i][2] = dp[i-1][0] + prices[i] # 卖出,要加钱!,前一天是持有
            dp[i][3] =  dp[i-1][2] # 冷冻期,前一天是卖出
        
        return max(dp[-1][1], max(dp[-1][2], dp[-1][3]))

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

文章讲解

思路:

类似第二题的多次买卖,需要在卖出赚钱时候-fee,然后由于卖出可能会亏钱,如果利润<fee,那么最后最大的金额是max(dp[-1][0], dp[-1][1])
class Solution:
    def maxProfit(self, prices: List[int], fee: int) -> int:
        # dp[i][0]持有 dp[i][1]不持有
        if not prices:
            return 0
        n = len(prices)

        dp = [[0,0] 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) # 不持有  注意要-fee!

        return max(dp[-1][0], dp[-1][1]) # 注意2!

股票问题终于做完了orz,含有冷冻期的状态比较复杂得多复习~加油!