mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-08-06 18:24:23 +08:00
4.6 KiB
4.6 KiB
思路
本题相对于贪心算法: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 + fee) {
result += prices[i] - minPrice - fee;
minPrice = prices[i] - fee; // 情况一,这一步很关键
}
}
return result;
}
};
从代码中可以看出对情况一的操作,因为如果还在收获利润的区间里,表示并不是真正的卖出,而计算利润每次都要减去手续费, 所以要让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++) {
// 第i天持股票所剩最多现金 = max(第i-1天持股票所剩现金, 第i-1天持现金-买第i天的股票)
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
// 第i天持有最多现金 = max(第i-1天持有的最多现金,第i-1天持有股票所剩的最多现金+第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]);
}
};
当然可以对空间经行优化,因为当前状态只是依赖前一个状态。
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;
}
};
细心的同学可能发现,在计算saleStock的时候 使用的已经是最新的holdStock了,理论上应该使用上一个状态的holdStock即(i-1时候的holdstock),但是