【LeetCode】714、買賣股票的最佳時機含手續費


Best Time to Buy and Sell Stock with Transaction Fee

題目等級:Medium

題目描述:

Your are given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee.

You may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.)

Return the maximum profit you can make.

Example 1:

Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
Output: 8
Explanation: The maximum profit can be achieved by:
Buying at prices[0] = 1
Selling at prices[3] = 8
Buying at prices[4] = 4
Selling at prices[5] = 9
The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.

  題意:給定一個整數數組 prices,其中第 i 個元素代表了第 i 天的股票價格 ;非負整數 fee 代表了交易股票的手續費用。可以無限次地完成交易,但是每次交易都需要付手續費。返回獲得利潤的最大值。


解題思路(動態規划):

  終於到了買賣股票的最后一道題。。。

  有了上一題(冷凍期)的經驗,這道題實際不難了,同樣是無數次情況的一個變形,只不過每次需要交一定的費用。實際很類似,有了上一題狀態的定義,稍加修改就是這個題了。

  同樣的,每一天是一個階段,每一階段的決策就是:每天決定買還是賣,而每一天有兩個狀態:手里持有股票、手里沒有股票

  和上題一樣,仍然定義兩個狀態變量:

  sell[i]:表示在第i天結束后手里沒有股票的情況下,獲得的最大收益。

  hold[i]:表示在第i天結束后手里仍然持有股票的情況下獲得的最大收益。

  其狀態轉移也不難分析:

  如果當天結束時仍然持有股票,那么有兩種可能:(1)今天剛買的,那么說明前一天結束的時候手里沒有股票了,即hold[i]=sell[i-1]-prices[i]. (2)以前就買了,今天啥也沒干,也沒買也沒賣,換句話說就是前一天結束的時候手里已經有了,即:hold[i]=hold[i-1]

  如果當天結束的時候手里沒有股票,那么說明也有兩種可能:(1)今天剛賣了, 也就是說前一天結束的時候手里還是持有股票的,而今天賣的時候還有交納費用,所以:sell[i]=hold[i-1]+prices[i]-fee.(2)以前就賣了,今天啥也沒干,那說明前一天結束的時候手里已經沒有股票了,所以:sell[i]=sell[i-1].

  綜合起來,就可以得到狀態轉移方程:

	hold[i]=max(sell[i-1]-prices[i],hold[i-1])
	sell[i]=max(hold[i-1]+prices[i]-fee,sell[i-1])

  初始條件還是一樣的,第一天的時候不可能賣出,一定會買入,這實際上還是貪心思想的一種體現,第一天可以買一定是會買的,在處理不限次數的交易時,已經證明了這種貪心思想的正確性,所以sell[0]=0,而hold[0]=-prices[0].

  最后,根據以上分析給出以下代碼:

    public int maxProfit(int[] prices, int fee) {
        if(prices==null || prices.length==0)
            return 0;
        int len=prices.length;
        int[] sell=new int[len];
        int[] hold=new int[len];
        sell[0]=0;
        hold[0]=-prices[0];
        for(int i=1;i<len;i++){
            sell[i]=Math.max(sell[i-1],hold[i-1]+prices[i]-fee);
            hold[i]=Math.max(sell[i-1]-prices[i],hold[i-1]);
        }
        return sell[len-1];
    }
}

  時間復雜度:O(n),空間復雜度:O(2n)

總結

  本題是買賣股票6道題的最后一題了,做一個簡單的總結,這一系列題目是動態規划和貪心思想的運用。我們可以看到:實際上在冷凍期和需要費用的這兩道題目中定義的兩個狀態sell和hold是可以解決所有的不限制交易次數的題目的,包括我們的無數次交易也可以通過這兩個狀態來寫出轉移方程,因為不管條件如何變,只要沒有限制交易次數,每天的狀態都還是這兩個。而限制了交易次數的,狀態就會復雜一些,就需要一個二維狀態,這也就是在允許交易K次的題目中我們給出的方法。

  因此,到此為止,不管股票買賣這道題再給出什么條件,我們都可以做了,因為限制次數的和不限制次數的兩種情況下的狀態我們都清楚了,只需要根據不同的條件寫出轉移方程就可以了。

  一次交易:【LeetCode】121、買賣股票的最佳時機

  兩次交易:【LeetCode】123、買賣股票的最佳時機 III

  K次交易:【LeetCode】188、買賣股票的最佳時機 IV

  無數次交易:【LeetCode】122、買賣股票的最佳時機 II

  無數次交易含冷凍期:【LeetCode】309、最佳買賣股票時機含冷凍期

  無數次交易含交易費用:【LeetCode】714、買賣股票的最佳時機含手續費


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM