题目描述
给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
做题情况
- 做出来且思路与标答一致 ☑
- 做出来但思路较为复杂
- 有思路,但时间复杂度较高无法通过
- 没有思路
自己的想法:动态规划
本题的重点在于当天可以买卖,因此我们可以确保当天一定持有当天的股票,即当天的具体情况仅仅依赖于前一天。每天可能持有股票或者不持有股票,所以根据前一天和当天的状态一共有2*2=4种情况。
如果当天持有股票,则可能前一天不持有,买了今天的股票,或者前一天持有,卖掉买了今天的股票或者换成了今天的股票(后者只需要买前一天的股票时改为不买即可)。
如果当前不持有股票,则可能前一天不持有,今天同样不持有,或昨天持有,今天卖掉了。
因为最终持有股票一定是差于不持有股票,所以直接可以得到最终的结果。
标答2:贪心
如果当天的价格高于之前持有的,则可以抛弃之前持有的,选择当天的。如果低于,则可以低买高卖,再买当天的股票。所以我们不需要考虑不持有股票的情况,只要当前价格低于持有的价格,就换掉,如果高于,则低买高卖再买下来。
实际代码
lass Solution {
public:
int maxProfit(vector<int>& prices)
{
/*
//自己也只能往动态规划的方向去想了。
//在一个点只有四种操作,继续持有手里的股票,卖掉手里的股票,买当前的股票,不动
//但最终的结果只有两种情况,手里有股票,以及手里没有股票
//是可以贪心的,此时不持有就是
int n=prices.size();
vector<vector<int>> vec(n,vector<int>(2,0));
vec[0][0]=0;
vec[0][1]=0;
for (int i=1;i<n;++i)
{
vec[i][0]=max(vec[i-1][0],vec[i-1][1]+prices[i]-prices[i-1]);
vec[i][1]=max(vec[i-1][1]+prices[i]-prices[i-1],vec[i-1][0]);
}
return vec[n-1][0];
*/
int res=0;
int n=prices.size();
int now=prices[0];
for (int i=1;i<n;++i)
{
if (prices[i]>now)
{
res+=prices[i]-now;
now=prices[i];
}
else
{
now=prices[i];
}
}
return res;
}
};
总结
重点是当天可以买卖,且时间要求其实锁住了很多比较慢的算法了,这道题的规模最慢支持O(nlogn)的算法,且顺序有用无法打乱,一些数据结构又用不了,所以只能用O(n)的算法了,即贪心或者只考虑前者的动态规划了。
另外对于只考虑前者的动态规划,我们完全可以不用数组保存,只用两位保存即可,可以大幅度降低空间复杂度(虽然空间复杂度一般来说都不会卡你)。