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

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/

解法一:dp

dp1[i] = max(dp[i-1], prices[i] - minval) 从前往后遍历,表示第1天买入,第i天之前卖出(包括第i天)的最大利润

dp2[i] = max(dp[i+1], maxval - prices[i]) 从后往前遍历,表示第i天之后(包括第i天)买入,第n天卖出的最大利润;

res = max(dp1 + dp2),因为(dp1 + dp2)[i] 正好表示从第1天到第n天经过最多两次交易的最大利润,我们的目标是找到令总利润最大的i。注意虽然不能同时参与多笔交易,但是卖出和买入可以在同一天进行(先卖后买)

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n = len(prices)       
        if n < 2:
            return 0
        dp1 = [0 for _ in range(n)]
        dp2 = [0 for _ in range(n)]
        min_val, max_val = prices[0], prices[n-1]
        #前向
        for i in range(1, n):
            dp1[i] = max(dp1[i-1], prices[i]-min_val)
            min_val = min(min_val, prices[i])
        #后向
        for i in range(n-2, -1, -1):
            dp2[i] = max(dp2[i+1], max_val-prices[i])
            max_val = max(max_val, prices[i])
        #合并输出
        return max([dp1[i]+dp2[i] for i in range(n)])

解法二:状态机dp

相当于状态机模型中k=2,直接套用188买卖股票的最佳时机 IV的解法,令k=2即可

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n = len(prices)
        k=2  #令k=2即可套用模板
        if  n == 0:
            return 0
        dp = [[[0] * 2 for _ in range(k + 1)] for _ in range(n+1)]

        for i in range(n + 1):
            for j in range(k + 1):
                if i  == 0:
                    dp[i][j][0] = 0
                    dp[i][j][1] = -sys.maxsize
                    continue
                if j  == 0:
                    dp[i][j][0] = 0
                    dp[i][j][1] = -sys.maxsize
                    continue
                dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i-1])
                dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i-1])
        return dp[n][k][0]

最后更新于