[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; } };
類似題目:
參考資料: