給定一個整數數組 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.
一、思路
(一)貪心算法
思路很簡單,從後往前遍歷數組,遇到高價則將其設置爲出售價格,每次出售股票時,計算當前利潤與上一次利潤之和,再計算一下此次交易若以上一次的售價出售,所能得到的利潤,對比兩者的大小,選擇利潤高的方式出售。
C++代碼:
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
// 初始化售價、購買價、上一次出售價、如果以上一次售價出售所能得到的利潤
int sale=prices[prices.size()-1], pre_sale=0, pur=0, fit;
// 總利潤、當前這次交易的利潤、上一次交易的利潤
int profit=0, cur_profit=0, pre_profit=0;
for(int i=prices.size()-2; i >= 0; i--){
if(prices[i] > sale){
sale = prices[i];
continue;
}
// 準備買賣
pur = prices[i];
cur_profit = sale - pur - fee;
fit = pre_sale - pur - fee;
if(fit > 0 && fit >= max(pre_profit + cur_profit, pre_profit)){
profit = profit - pre_profit + fit;
pre_profit = fit;
sale = pur;
continue;
}
if(cur_profit > 0){
profit += cur_profit;
pre_profit = cur_profit;
pre_sale = sale;
sale = pur;
}
}
return profit;
}
};
(二)動態規劃
1、狀態轉移框架
建立動態規劃表:
- i:表示第i天
- j:表示當前股票的持有狀態,0表示沒有持有股票,1表示持有股票
動態規劃表的意義就很明顯了,就在第i天時,手裏持有股票(j=1)或者沒有持股(j=0)所能獲取的最大利潤。
除此之外,在這一天,還有3種操作可選:buy、sell、rest。
我們現在要做的就是遍歷所有可能的狀態,求出利潤最大的,那麼這裏的解題僞代碼可以寫成:
for 0 <= i < n:
for j in {0, 1}:
dp[i][j] = max{buy, sell, rest}
於是所求的答案爲:
4、狀態轉移方程
這個方程表達的意思是:在第i天,手裏沒有持股,所能獲取的最大利潤爲
那麼這個利潤是怎麼來的?這要從當前的狀態分析,因爲當前沒有持股,要麼昨天沒有持股,要麼昨天持股,但是今天賣掉了,這裏賣掉需要減去一個手續費纔是最終的利潤。
這個方程表達的意思是:在第i天,手裏持股,所能獲取的最大利潤爲
那麼這個利潤是怎麼來的?這要從當前的狀態分析,因爲當前持股,要麼昨天持股,要麼昨天沒有持股,但是今天買入了股票。
C++代碼:
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
if(prices.size() == 0 || prices.size() == 1)
return 0;
vector<vector<int>> dp(prices.size(), vector<int>(2, 0));
// 初始化
dp[0][1] = -prices[0];
dp[1][0] = max(dp[0][0], dp[0][1] + prices[1] - fee);
dp[1][1] = max(dp[0][1], dp[0][0] - prices[1]);
// 狀態轉移
for(int i=2; i < prices.size(); i++){
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i] - fee);
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]);
}
return dp[prices.size() - 1][0];
}
};