一、题意
给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。求获得利润的最大值。
二、解法
解法一:
动态规划
有两种状态:
dp[i][0]
:没有持股时的最大收益
dp[i][1]
:持股时的最大收益
dp[i][0]
是前一天没有持股的最大收益dp[i-1][0]
和今天将昨天的股票卖出所获得的最大收益dp[i-1][1]+prices[i]
中的最大值
dp[i][1]
是前一天持股的最大收益dp[i-1][1]
和昨天没有持股今天买入所获最大收益dp[i-1][1]-prices[i]-fee
的最大值。
最后dp[n-1][0]
即为答案
优化空间
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
解法二(官方解法,不是很理解):
贪心
buy表示当前买入的价格
prices[i]+fee
比buy小,就抛掉手上的,买入当前的。
如果prices[i]>buy,就分红入账,入账后,buy=prices[i]
,收益已拿到手,接下来就要跟prices[i]比较大小。
三、代码
解法一
int maxProfit(vector<int>& prices, int fee) {
int ans = 0;
int dp[2];
dp[0]=0;
dp[1]=-prices[0]-fee;
for(int i=1;i<prices.size();i++){
int d0=dp[0],d1=dp[1];
dp[0] = max(d0,d1+prices[i]);
dp[1]=max(d1,d0-prices[i]-fee);
}
return dp[0];
}
解法二
int maxProfit(vector<int>& prices, int fee) {
int n = prices.size();
int buy = prices[0] + fee;
int profit = 0;
for (int i = 1; i < n; ++i) {
if (prices[i] + fee < buy) {
buy =min( prices[i] + fee,buy);
}
else if (prices[i] > buy) {
profit += prices[i] - buy;
buy = prices[i];
}
}
return profit;
}
四、总结
第一种方法比较容易理解,根据leetcode:leetcode 309. Best Time to Buy and Sell Stock with Cooldown能编出来,第二种不好理解。
五、引用
[1] leetcode:714. Best Time to Buy and Sell Stock with Transaction Fee
[2] leetcode:714. Best Time to Buy and Sell Stock with Transaction Fee官方解法