[LeetCode] Best Time to Buy and Sell Stock with Transaction Fee 買股票的最佳時間含交易費


 

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.

 

Note:

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

 

又是一道股票交易的題,之前已經有過類似的五道題了,fun4LeetCode大神的帖子做了amazing的歸納總結,有時間的話博主也寫個總結。這道題跟Best Time to Buy and Sell Stock II其實最像,但是由於那道題沒有交易費的限制,所以我們就無腦貪婪就可以了,見到利潤就往上加。但是這道題有了交易費,所以當賣出的利潤小於交易費的時候,我們就不應該賣了,不然虧了。所以這道題還是還是得用動態規划來做,按照fun4LeetCode大神的理論,本質其實是個三維dp數組,由於第三維只有兩種情況,賣出和保留,而且第二維交易的次數在這道題中沒有限制,所以我們用兩個一維數組就可以了,sold[i]表示第i天賣掉股票此時的最大利潤,hold[i]表示第i天保留手里的股票此時的最大利潤。那么我們來分析遞推公式,在第i天,如果我們要賣掉手中的股票,那么此時我們的總利潤應該是前一天手里有股票的利潤(不然沒股票賣毛啊),加上此時的賣出價格,減去交易費得到的利潤總值,跟前一天賣出的利潤相比,取其中較大值,如果前一天賣出的利潤較大,那么我們就前一天賣了,不留到今天了。然后來看如果第i天不賣的利潤,就是昨天股票賣了的利潤然后今天再買入股票,得減去今天的價格,得到的值和昨天股票保留時的利潤相比,取其中的較大值,如果昨天保留股票的利潤大,那么我們就繼續保留到今天,所以遞推時可以得到:

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

hold[i] = max(hold[i - 1], sold[i - 1] - prices[i]);

參見代碼如下:

 

解法一:

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        vector<int> sold(prices.size(), 0), hold = sold;
        hold[0] = -prices[0];
        for (int i = 1; i < prices.size(); ++i) {
            sold[i] = max(sold[i - 1], hold[i - 1] + prices[i] - fee);
            hold[i] = max(hold[i - 1], sold[i - 1] - prices[i]);
        }
        return sold.back();
    }
};

 

我們發現不管是賣出還是保留,第i天到利潤只跟第i-1天有關系,所以我們可以優化空間,用兩個變量來表示當前的賣出和保留的利潤,更新方法和上面的基本相同,就是開始要保存sold的值,不然sold先更新后,再更新hold時就沒能使用更新前的值了,參見代碼如下:

 

解法二:

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int sold = 0, hold = -prices[0];
        for (int price : prices) {
            int t = sold;
            sold = max(sold, hold + price - fee);
            hold = max(hold, t - price);
        }
        return sold;
    }
};

 

類似題目:

Best Time to Buy and Sell Stock with Cooldown

Best Time to Buy and Sell Stock IV

Best Time to Buy and Sell Stock III

Best Time to Buy and Sell Stock II

Best Time to Buy and Sell Stock

 

參考資料:

https://discuss.leetcode.com/topic/107992/java-dp-solution-easy-understand

https://discuss.leetcode.com/topic/107977/c-concise-solution-o-n-time-o-1-space

https://discuss.leetcode.com/topic/107998/most-consistent-ways-of-dealing-with-the-series-of-stock-problems

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

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



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