题目:
今天是正式开始独立思考动态规划解题的日子。
这题拿到手的时候,我第一时间其实想到的就是动态规划,去找他每天最大收益状态,但是想来想去发现行不通,于是就作弊看答案了,发现是使用双状态的方法考虑的。
答案是这么考虑这个问题的:
1.每天的状态分为持有和不持有股票两种状态。而今日收益肯定就是这两种状态的其中一种,所以只要写出这两种状态的状态转移方程即可。
2.首先对于今天交易结束以后不持有股票的收益,存在两种情况,第一种,是延续昨天的不持有股票,或者是今天将股票卖出了。
那么今天不持有股票状态的收益就应该是:
(1)昨天不持有股票的收益
(2)今天持有昨天的股票但是卖出了的收益
这两项收益值最大的那个
3.对于今天交易结束以后持有股票的收益,同样也存在两种情况,第一种是延续昨天持有股票,或者是今天买入了。其它的同理2
写代码的时候,发现评论区有一个大神的代码写的比官方题解更好,不需要二维数组那么复杂的操作,因为只有两个变量需要更改,暂存就可以了
C++代码:(附带测试)
#include<iostream>#include<vector>using namespace std;class Solution {public:int maxProfit(vector<int>& prices, int fee) {if (prices.empty() || fee < 0) return 0;int n = prices.size();// 每天的股票状态分为: 持有 vs 不持有;// 今天的持有状态收益: from max {昨天的持有状态保持不动, 昨天未持有今天买入 }// 今天的不持有状态收益: from max {昨天的不持有状态保持不动, 昨天持有今天卖掉 }int noHold = 0, hold = -prices[0]; // 第1天;int tmp = 0; // 存储临时值;for (int i = 1; i < n; ++i) {tmp = hold;// 保持昨天的持有状态过渡 或者 昨天不持有那今天一定得买[持有];hold = max(hold, noHold - prices[i]);// 保持昨天的不持有状态过渡 或者 昨天持有那今天一定得卖掉[不持有];noHold = max(noHold, tmp + prices[i] - fee);}return noHold; // 返回最后一天不持有股票的累计利润;}};int main(){vector<int> prices = {1, 3, 2, 8, 4, 9};int fee = 2;Solution s;cout<<s.maxProfit(prices,fee);}
贪心的思想也很有意思,我一开始本来觉得这条路是行不通的。
官方题解浓缩的很好:
当我们卖出一支股票时,我们就立即获得了以相同价格并且免除手续费买入一支股票的权利
什么意思呢?就是我们希望我们每次卖出股票获得的收益都必须大于等于收益值。但是由于贪心算法会在大于手续费的收益时就选择卖出,所以还需要一个细节的处理,即minPrice = prices[i] - fee,这样在之后收获利润的时候,才不会多计算一次手续费
C++代码:
class Solution {public: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 = prices[i] + fee;}else if (prices[i] > buy) {profit += prices[i] - buy;buy = prices[i];//这里是最关键的细节}}return profit;}};作者:LeetCode-Solution链接:https://leetcode-/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-han-sh-rzlz/来源:力扣(LeetCode)著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果觉得《【LeetCode刷题笔记-39 714.买卖股票的最佳时机(含手续费)】》对你有帮助,请点赞、收藏,并留下你的观点哦!