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】123、買賣股票的最佳時機 III
K次交易:【LeetCode】188、買賣股票的最佳時機 IV
無數次交易:【LeetCode】122、買賣股票的最佳時機 II
無數次交易含冷凍期:【LeetCode】309、最佳買賣股票時機含冷凍期
無數次交易含交易費用:【LeetCode】714、買賣股票的最佳時機含手續費