LeetCode123:買賣股票的最佳時機 III

問題121:給定一個數組,它的第i個元素是給定股票第i天的價格。如果你最多只能買入和賣出兩次,設計一個算法來計算你所能獲取的最大利潤。注意:你不能在買入股票前賣出股票。

解法一:切成兩段,每段分別用第121題的方法,求兩段和最大值;

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        def maxPro(prices):
            if not prices:
                return 0
            dif = []
            predp = 0
            ans = 0
            for i in range(1, len(prices)):
                dif = prices[i] - prices[i-1]
                predp = max(dif, dif + predp)           
                ans = max(predp, ans)
            return ans
        
        max_pro = 0
        for mid in range(0, len(prices)):
            cur_pro = maxPro(prices[:mid+1]) + maxPro(prices[mid+1:])
            if cur_pro > max_pro:
                max_pro = cur_pr
        return max_pro

這種方法比較直觀,但是會超時。

解法二:動態規劃。

這種解法,比較難理解,也可能是我太菜了,自己從頭到尾推了一遍,才勉強理解。

舉個例子,對于[7, 1, 5, 3, 6, 4], 其狀態轉移圖如下所示。先遍歷列,再遍歷行。注意,輸出的是max(0, max(dp[len(prices)][2], dp[len(prices)][4])),因為最大利潤既可能在第一次賣出時獲得,又可能在第二次賣出時獲得。如果操作一定虧損,干脆不進行任何操作,直接輸出0

完整代碼:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        dp = [[float('-inf') for _ in range(5)] for _ in range(len(prices)+1)]
        for i in range(len(prices)+1):
            dp[i][0] = 0
        for i in range(1, len(prices)+1):
            for j in range(1, 5):          
                if j % 2 == 1:
                    dp[i][j] = max(dp[i-1][j-1] - prices[i-1], dp[i-1][j])
                else:
                    dp[i][j] = max(dp[i-1][j-1] + prices[i-1], dp[i-1][j])
        return max(0, max(dp[len(prices)][2], dp[len(prices)][4]))

運行結果:

與背包問題類似,我們可以對該程序進行優化,優化到一維。
注意,j要從后往前遍歷,因為計算dp[j]的時候,dp[j]的值依賴于dp[j-1],而此時的dp[j-1]應該是第i-1輪的,而不是第i輪的。所以,一定要在更新dp[j-1]之前更新dp[j],因此j要從后往前遍歷。同時,這也是先遍歷i,再遍歷j的原因。

優化代碼:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        dp = [float('-inf') for _ in range(5)]
        dp[0] = 0        
        for i in range(1, len(prices)+1):
            #j從后往前遍歷
            for j in range(4, 0, -1):
                if j % 2 == 1:
                    dp[j] = max(dp[j-1] - prices[i-1], dp[j])
                else:
                    dp[j] = max(dp[j-1] + prices[i-1], dp[j])
        return max(0, max(dp[2], dp[4]))

運行結果:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。