「leetcode」714. 買賣股票的最佳時機含手續費 超詳細講解
本文 https://github.com/youngyangyang04/leetcode-master 已經收錄,裡面還有leetcode刷題攻略、各個型別經典題目刷題順序、思維導圖,可以fork到自己倉庫,有空看一看一定會有所收穫,如果對你有幫助也給一個star支援一下吧!
714. 買賣股票的最佳時機含手續費
題目連結:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
給定一個整數陣列 prices,其中第 i 個元素代表了第 i 天的股票價格 ;非負整數 fee 代表了交易股票的手續費用。
你可以無限次地完成交易,但是你每筆交易都需要付手續費。如果你已經購買了一個股票,在賣出它之前你就不能再繼續購買股票了。
返回獲得利潤的最大值。
注意:這裡的一筆交易指買入持有並賣出股票的整個過程,每筆交易你只需要為支付一次手續費。
示例 1:
輸入: prices = [1, 3, 2, 8, 4, 9], fee = 2
輸出: 8
解釋: 能夠達到的最大利潤:
在此處買入 prices[0] = 1
在此處賣出 prices[3] = 8
在此處買入 prices[4] = 4
在此處賣出 prices[5] = 9
總利潤: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
注意:
- 0 < prices.length <= 50000.
- 0 < prices[i] < 50000.
- 0 <= fee < 50000.
思路
本題相對於貪心演算法:122.買賣股票的最佳時機II,多新增了一個條件就是手續費。
貪心演算法
在貪心演算法:122.買賣股票的最佳時機II中使用貪心策略不用關心具體什麼時候買賣,只要收集每天的正利潤,最後穩穩的就是最大利潤了。
而本題有了手續費,就要關係什麼時候買賣了,因為計算所獲得利潤,需要考慮買賣利潤可能不足以手續費的情況。
如果使用貪心策略,就是最低值買,最高值(如果算上手續費還盈利)就賣。
此時無非就是要找到兩個點,買入日期,和賣出日期。
- 買入日期:其實很好想,遇到更低點就記錄一下。
- 賣出日期:這個就不好算了,但也沒有必要算出準確的賣出日期,只要當前價格大於(最低價格+手續費),就可以收穫利潤,至於準確的賣出日期,就是連續收穫利潤區間裡的最後一天(並不需要計算是具體哪一天)。
所以我們在做收穫利潤操作的時候其實有三種情況:
- 情況一:收穫利潤的這一天並不是收穫利潤區間裡的最後一天(不是真正的賣出,相當於持有股票),所以後面要繼續收穫利潤。
- 情況二:前一天是收穫利潤區間裡的最後一天(相當於真正的賣出了),今天要重新記錄最小价格了。
- 情況三:不作操作,保持原有狀態(買入,賣出,不買不賣)
貪心演算法C++程式碼如下:
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int result = 0;
int minPrice = prices[0]; // 記錄最低價格
for (int i = 1; i < prices.size(); i++) {
// 情況二:相當於買入
if (prices[i] < minPrice) minPrice = prices[i];
// 情況三:保持原有狀態(因為此時買則不便宜,賣則虧本)
if (prices[i] >= minPrice && prices[i] <= minPrice + fee) {
continue;
}
// 計算利潤,可能有多次計算利潤,最後一次計算利潤才是真正意義的賣出
if (prices[i] > minPrice + fee) {
result += prices[i] - minPrice - fee;
minPrice = prices[i] - fee; // 情況一,這一步很關鍵
}
}
return result;
}
};
- 時間複雜度:O(n)
- 空間複雜度:O(1)
從程式碼中可以看出對情況一的操作,因為如果還在收穫利潤的區間裡,表示並不是真正的賣出,而計算利潤每次都要減去手續費,所以要讓minPrice = prices[i] - fee;,這樣在明天收穫利潤的時候,才不會多減一次手續費!
大家也可以發現,情況三,那塊程式碼是可以刪掉的,我是為了讓程式碼表達清晰,所以沒有精簡。
動態規劃
我在公眾號「程式碼隨想錄」裡將在下一個系列詳細講解動態規劃,所以本題解先給出我的C++程式碼(帶詳細註釋),感興趣的同學可以自己先學習一下。
相對於貪心演算法:122.買賣股票的最佳時機II的動態規劃解法中,只需要在計算賣出操作的時候減去手續費就可以了,程式碼幾乎是一樣的。
C++程式碼如下:
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
// dp[i][1]第i天持有的最多現金
// dp[i][0]第i天持有股票所剩的最多現金
int n = prices.size();
vector<vector<int>> dp(n, vector<int>(2, 0));
dp[0][0] -= prices[0]; // 持股票
for (int i = 1; i < n; i++) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);
}
return max(dp[n - 1][0], dp[n - 1][1]);
}
};
- 時間複雜度:O(n)
- 空間複雜度:O(n)
當然可以對空間經行優化,因為當前狀態只是依賴前一個狀態。
C++ 程式碼如下:
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int n = prices.size();
int holdStock = (-1) * prices[0]; // 持股票
int saleStock = 0; // 賣出股票
for (int i = 1; i < n; i++) {
int previousHoldStock = holdStock;
holdStock = max(holdStock, saleStock - prices[i]);
saleStock = max(saleStock, previousHoldStock + prices[i] - fee);
}
return saleStock;
}
};
- 時間複雜度:O(n)
- 空間複雜度:O(1)
總結
本題貪心的思路其實是比較難的,動態規劃才是常規做法,但也算是給大家擴充一下思路,感受一下貪心的魅力。
後期我們在講解 股票問題系列的時候,會用動規的方式把股票問題穿個線。
我是程式設計師Carl,可以找我組隊刷題,也可以在B站上找到我,本文leetcode刷題攻略已收錄,更多精彩演算法文章盡在公眾號:程式碼隨想錄,關注後就會發現和「程式碼隨想錄」相見恨晚!
如果感覺對你有幫助,不要吝嗇給一個?吧!
相關文章
- Day 44 | 714.買賣股票的最佳時機含手續費
- [力扣每日一題]714. 買賣股票的最佳時機含手續費力扣每日一題
- leetcode 動態規劃 買賣股票的最佳時機含手續費 javaLeetCode動態規劃Java
- 程式碼隨想錄演算法訓練營第48天 | 188.買賣股票的最佳時機IV 、309.最佳買賣股票時機含冷凍期、 714.買賣股票的最佳時機含手續費演算法
- LeetCode《買賣股票的最佳時機》系列題目,最詳解LeetCode
- leetcode 121 買賣股票的最佳時機LeetCode
- Leetcode121. 買賣股票的最佳時機LeetCode
- 買賣股票的最佳時機 IV javaJava
- leetcode 123 買賣股票的最佳時機 IIILeetCode
- leetcode 122 買賣股票的最佳時機 IILeetCode
- 121. 買賣股票的最佳時機
- [Leetcode]123.買賣股票的最佳時機3LeetCode
- LeetCode-122-買賣股票的最佳時機 IILeetCode
- LeetCode122. 買賣股票的最佳時機 IILeetCode
- LeetCode-Java:122. 買賣股票的最佳時機ⅡLeetCodeJava
- 程式碼隨想錄演算法訓練營 | 121.買賣股票的最佳時機,122.買賣股票的最佳時機II,123.買賣股票的最佳時機III演算法
- Java演算法之動態規劃詳解-買賣股票最佳時機Java演算法動態規劃
- 【LeetCode動態規劃#13】買賣股票含冷凍期(狀態眾多,比較繁瑣)、含手續費LeetCode動態規劃
- 力扣之陣列——買賣股票的最佳時機力扣陣列
- 力扣-121. 買賣股票的最佳時機力扣
- LeetCode 188 買賣股票的最佳時機IV HERODING的LeetCode之路LeetCode
- 線性dp:LeetCode122.買賣股票的最佳時機llLeetCode
- 陣列筆試題之買賣股票的最佳時機陣列筆試
- leetcode【每日一題】122. 買賣股票的最佳時機 II JavaLeetCode每日一題Java
- 力扣-122. 買賣股票的最佳時機 II力扣
- 【LeetCode】309. Best Time to Buy and Sell Stock with Cooldown 最佳買賣股票時機含冷凍期(Medium)(JAVA)LeetCodeJava
- 演算法122. 買賣股票的最佳時機 II演算法
- 【演算法】【線性表】【陣列】買賣股票的最佳時機演算法陣列
- 【演算法】【線性表】【陣列】買賣股票的最佳時機 II演算法陣列
- Leetcode121、買賣股票的最佳時機(Python題解)只買一次,位元組跳動面試題LeetCodePython面試題
- 【leetcode】40-best-time-to-buy-and-sell-stock 力扣 121. 買賣股票的最佳時機LeetCode力扣
- 演算法系列-動態規劃(4):買賣股票的最佳時機演算法動態規劃
- 詳解股票買賣演算法的最優解(一)演算法
- Go Struct超詳細講解GoStruct
- 【LeetCode動態規劃#12】詳解買賣股票I~IV,經典dp題型LeetCode動態規劃
- A*演算法(超級詳細講解,附有舉例的詳細手寫步驟)演算法
- 42-best-time-to-buy-and-sell-stock-iii 力扣 123. 買賣股票的最佳時機 III力扣
- lintcode [python]151. 買賣股票的最佳時機 III你最多可以完成兩筆交易。Python