算法課作業系列(7)
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.
思路
其實這道題不算難,主要考的是動態規劃的問題,受到揹包問題的影響,我自己想到一個算法,時間複雜度爲O(n^2),而提交之後給出了超時的判定,在查看討論區後,自己又根據別人的思想,寫好了第二個算法。
值得一提的是,動態規劃的算法大多數都比較短小,而思想也是把原問題分解之後求解,和分治類似。在想到動態規劃的算法之前可能題目會很複雜,但是一旦找到了狀態轉移式之後,一切也就迎刃而解了,那麼接下來就來看看這兩個思路。
- 從後往前
其實這個想法個人認爲是很自然而然的,要求最大利益,無非就是當天兩種可能,賣或者不賣,先把公式表示出來:
C(i) = max{p(j) - p(i) - fee + C(j), C(i + 1)} j->(i + 1, n)
下面來詳細說說這個式子,C代表最大利潤,p爲價格,那麼第i天的最大利潤就是第j天賣出加上第j天開始的最大利潤
和i+1天的利潤
的最大值。怎麼去理解呢?假設我第i天是持有貨物的,那麼我的利潤就是第j天賣出得到的利潤,而第j天又可以買入新的貨物,因此要加上第j天的最大利潤;而如果我第i天手上沒有貨物,則我第i天的利潤也就是第i+1天的利潤,具體是第i天買入之後賣出還是第j天什麼都不做,就要看這兩種結果誰更大就好。我們的前面的值是依賴後面的,因此我們要從最後一天開始往前看,最後一天一定是什麼都不做,利潤爲0,繼續往前,只要分解成小問題就可以了,具體的參考上面的公式。 - 從前往後
上面那個是我個人的思考,這裏介紹一下另外一個思路,同樣的先給出公式
HOLD(i) = max{HOLD(i - 1), SOLD(i - 1) - p(i)}
SOLD(i) = max{SOLD(i - 1), HOLD(i - 1) + p(i) - fee}
上面的HOLD代表第i天持有貨物的利潤,而SOLD代表第i天沒有貨物的利潤,因此我們可以知道:
HOLD(i)一種情況下是前一天沒有貨物,但是當天買了貨物;另一種情況是前一天有貨物,當天什麼都沒做,具體看上面的公式
SOLD(i)一種情況是前一天就沒有,當天什麼都沒做;另一種是前一天有,今天賣出了,可以參考上面公式
而第一天的話,考慮到沒有本金,那麼SOLD(0)就應該爲0,HOLD(0)就應該爲-p(0),這樣,我們的算法就設計出來啦!