天天看點

leetcode每日一題:714. 買賣股票的最佳時機含手續費

該題目:

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

給定一個整數數組 prices,其中第 i 個元素代表了第 i 天的股票價格 ;非負整數 fee 代表了交易股票的手續費用。

你可以無限次地完成交易,但是你每筆交易都需要付手續費。如果你已經購買了一個股票,在賣出它之前你就不能再繼續購買股票了。

傳回獲得利潤的最大值。

注意:這裡的一筆交易指買入持有并賣出股票的整個過程,每筆交易你隻需要為支付一次手續費。

示例 1:

輸入: prices = [1, 3, 2, 8, 4, 9], fee = 2
輸出: 8
解釋: 能夠達到的最大利潤:  
在此處買入 prices[0] = 1
在此處賣出 prices[3] = 8
在此處買入 prices[4] = 4
在此處賣出 prices[5] = 9
總利潤: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.           

複制

注意:

0 < prices.length <= 50000.
0 < prices[i] < 50000.
0 <= fee < 50000.           

複制

思路:

關于股票問題,一般是使用動态規劃解決,股票那天有兩種狀态,賣或者不賣,

* dp[i][0] 表示第 i天不持有可獲得的最大利潤;

* dp[i][1] 表示第 i 天持有可獲得的最大利潤(注意是第 i天持有,而不是第 i天買入)

假設沒有任何限制,定義狀态轉移方程:

不持有:

dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])           

複制

對于今天不持有,可以從兩個狀态轉移過來:

1. 昨天也不持有;2. 昨天持有,今天賣出。兩者取較大值。

持有:

dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])           

複制

對于今天持有,可以從兩個狀态轉移過來:

1. 昨天也持有;2. 昨天不持有,今天買入。兩者取較大值。

此時變體會有一些條件限制,比如限制交易次數, 有交易費用等。大體思路是在上述思路上進行變化。

本題是賣出會有交易費用,相應的公示進行修改即可

class Solution:
    def maxProfit(self, prices: List[int], fee: int) -> int:
        if prices is None or len(prices) < 1:
            return 0
        length = len(prices)
        # DP, 與之前一樣,沒有冷凍期,隻是需要加一個賣出時候的手續費, 無限k
        # dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i] - fee)
        # dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
        dp_i_0 = 0
        dp_i_1 = float('-inf')
        for i in range(length):
            tmp = dp_i_0
            dp_i_0 = max(dp_i_0, dp_i_1 + prices[i] - fee)
            dp_i_1 = max(dp_i_1, tmp - prices[i])
        return dp_i_0           

複制

可以參考:

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/solution/si-chong-shi-xian-tu-jie-714-mai-mai-gu-piao-de-zu/