题目分析
股票买入后不能在买,也就是必须买入后卖出才能买
一次交易叫买卖,这样的交易次数不能超过两次
返回最大利润
算法原理
状态表示:
经验+题目要求
经验:以i位置为结尾,巴拉巴拉
题目要求:以i位置为结尾,所能获得的最大利润
细分状态:由于通过题目可以得出,i天结束后可能处于买入状态或者卖出状态(买入就是i天结束后手里有股票,卖出就是i天结束后手里没股票)
此时又发现,题目要求最多只能交易两次,也就是你能交易0/1/2次
所以状态又可以细分,i天结束后,处于买入状态,此时交易了0次
i天结束后,处于买入状态,此时交易了1次
等等6种情况
那我们可以简化一下,创建两个dp表,一个f,一个g
f[i][j]:表示第i天结束之后,完成了j次交易,此时处于买入状态,所能获得的最大利润
g[i][j]: 表示第i天结束之后,完成了j次交易,此时处于卖出状态,所能获得的最大利润
分析:f[i][j]=什么???
第i天结束时是买入状态:可以由第i-1天结束时买入状态(手里有股票)我不卖股票,此时就会i天结束后处于买入状态+由卖出(手里没股票)到买入(手里有股票)
第i天结束时是卖出状态:可以由i-1天结束时卖出状态(手里没股票),我不买股票,此时i天结束时就会处于卖出状态+由买到卖出(把手里股票卖了)
注意:我们这里处理交易次数是以卖出时才增加,你当然也可以买入的时候就增加
f[i][j]=max(f[i-1][j],g[i-1][j]-p[i]);
注意这里第i-1天的j是跟第i天的j一样的,因为你买入到买入,你的交易次数都没变,卖出也一样
g[i][j]=max(g[i-1][j],f[i-1][j-1]+p[i])
注意:卖出到卖出,交易次数肯定没变,但买入到卖出交易次数就变了,如果你i天交易次数是2,那么i-1天交易次数肯定是1,所以f那里的交易次数是j-1
初始化:
f[i][j]=max(f[i-1][j],g[i-1][j]-p[i]);
g[i][j]=max(g[i-1][j],f[i-1][j-1]+p[i])
这里发现你在算f的时候会用到i-1,所以需要我们初始化第一行,然后从第二行开始填表
这里发现你再算g的时候会用到i-1和j-1,所以我们需要初始化第一行和第一列,但这样过于麻烦,
也就是用填第一列时需要用到负一列的值,就是你今天是结束时是卖出状态,且交易次数为0,那你昨天交易次数肯定不能是-1吧,所以你可以这样处理先去g[i-1][j]的值
如果j-1>=0,亦或者你的j>=1,也就是你今天结束后处于卖出状态时你的交易次数至少为1;
f[0][0]的位置肯定设成-prices[0]代表你第1天结束后买了股票时的最大利润
而且此时你交易次数是0,因为我们上面处理了当你买了之后在卖交易次数才会+1
g[0][0]:填0,啥都不干
其他位置的填写不能影响下面的填表 :
第一天完成一笔交易和第一天完成两笔交易的情况根本就不存在
所以我们求max的时候就不要让f[0][1]和f[0][2]的位置的值干扰后面的结果,所以让他们的位置是负无穷就好,但有些编译器在处理时负无穷减去一个数字可能会得到一个正数,所以负无穷那里我们可以初始化成-0x3f3f3f3f(这个数字是int的一半)
为什么不是f表,你想想如果你手里有股票和手里没股票哪个的利润大