现在已将LeetCode刷题心得记录github上,每一题都有我能够想到的多种解法,欢迎star!github
该问题和121,122是一类问题,难度逐层递增,首先先考虑121题
只能交易一次,寻找最大利润,一开始想到的最简单的策略就是用一个值保存目前为止碰到的最小进价,和当前值相减后与当前最大利润比较,这样只需要两个额外变量即可,但是这样8ms只能打败30%的答案。
对于122题:
放宽了限制,可以进行无数次的交易,总利润最大就行,这时想到的一个最佳策略就是用一个数组表示和前一天相比的净利润,最后将数组中所有非负值相加即可。这样能够打败98%的答案。
针对123题,瞬间懵逼,要求能够进行两次交易,第一个想到的无非就是尝试DP,但是状态转移方程迟迟无法找到。。参考别人的思路后,原来该类问题可以利用状态机的方式进行解决,对于123题,可以设置4种状态,状态一 是第一次交易还没开始,可以选择的策略是继续保持或者进第一个货,状态二 是第一次交易还没有结束,以此类推。
方法如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()<2) return 0;
int s1=-prices[0],s2=INT_MIN,s3=INT_MIN,s4=INT_MIN;
for(int i=1;i<prices.size();i++)
{
s1=max(s1,-prices[i]);
s2=max(s2,s1+prices[i]);
s3=max(s3,s2-prices[i]);
s4=max(s4,s3+prices[i]);
}
return s4;
}
};
轻轻松松干掉99%的答案,同样可以将这种思路用到前面两题
对于121,状态机只有两种状态
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()<2) return 0;
int s1=-prices[0],s2=INT_MIN;
for(auto c:prices)
{
s1=max(s1,-c);
s2=max(s2,s1+c);
}
return s2;
}
};
对于122,是不是又感觉懵逼了,交易可以有无数次,这时可以考虑状态一和状态二的一个闭环
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()==0) return 0;
int s1=-prices[0],s2=0;
for(auto c:prices)
{
s1=max(s1,s2-c);
s2=max(s2,s1+c);
}
return s2;
}
};
这样就解决了无数次的问题,对于该类问题都可以使用这类方法解决。