第一种:限制交易次数k=1
第二种:不限制交易次数k=+inifnity
第三种k=2
第四种:限制交易次数为k
第五种,第六种:不限制交易次数,加了冷冻期和手续费
一、穷举框架
不用递归穷举:不发找完所有的计算冗余,使用状态穷举,状态只有三种买,卖,不操作,状态有先后之分
dp[i][k][0 or 1]可以穷举所有的状态
i表示天数,
k表示仍有的交易次数??(意思应该是已经发生了交易次数,总和不能超过K)
0表示未持有股票,1表示持有股票
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
max( 选择 rest , 选择 sell )
解释:今天我没有持有股票,有两种可能:
要么是我昨天就没有持有,然后今天选择 rest,所以我今天还是没有持有;
要么是我昨天持有股票,但是今天我 sell 了,所以我今天没有持有股票了。
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
max( 选择 rest , 选择 buy )
解释:今天我持有着股票,有两种可能:
要么我昨天就持有着股票,然后今天选择 rest,所以我今天还持有着股票;
要么我昨天本没有持有,但今天我选择 buy,所以今天我就持有股票了。
base case:
dp[-1][k][0] = 0
解释:因为 i 是从 0 开始的,所以 i = -1 意味着还没有开始,这时候的利润当然是 0 。
dp[-1][k][1] = -infinity
解释:还没开始的时候,是不可能持有股票的,用负无穷表示这种不可能。
dp[i][0][0] = 0
解释:因为 k 是从 1 开始的,所以 k = 0 意味着根本不允许交易,这时候利润当然是 0 。
dp[i][0][1] = -infinity
解释:不允许交易的情况下,是不可能持有股票的,用负无穷表示这种不可能。
base case:
dp[-1][k][0] = dp[i][0][0] = 0
dp[-1][k][1] = dp[i][0][1] = -infinity
状态转移方程:
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
第一题 k=1
dp[i][1][0] = max(dp[i-1][1][0], dp[i-1][1][1] + prices[i])
dp[i][1][1] = max(dp[i-1][1][1], dp[i-1][0][0] - prices[i])
= max(dp[i-1][1][1], -prices[i])
解释:k = 0 的 base case,所以 dp[i-1][0][0] = 0。
现在发现 k 都是 1,不会改变,即 k 对状态转移已经没有影响了。
可以进行进一步化简去掉所有 k:
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], -prices[i])
如何保证只买卖一次的?好像是通过max,
k在状态转移方程中都是1,所以就把k维给删了,这是数学公式上的逻辑
自然语言描述的逻辑是,买了又卖未持有股票赚97块,买了没卖持有股票-3元,下一波股票值一元,它的未持有股票来自于 未持有到未持有:97块,持有到未持有-2块,所以如果之前卖了股票,受益最大的话,这个值会在未持有股票 中一直存在,会比任何一轮持有到未持有的受益高,这一轮持有是来自于 未持有到持有,相当于买第二只股票,和持有到持有,一共买了两只股票
不能同时持双股,因为只有从未持有到持有 持有到未持有 才会有受益的变化,其他情况是不会变得,所以从持有到持有意思持有同一只股票保持状态不变
0表示未持有,1表示持有
0只能到0,1可以到0或者1,-prices可以到1,就保证了只能做一次交易,max只是保证了存储了到当前i时,能达到最大收益的情况。
dp[i][1]=max(dp[i-1][1],-prices[i])是上一轮的1和本次的i的价格,并不是上一轮的0相比,所以本次如果要买股票,也一定是第一次买股票
第二题 k=+infinity
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
= max(dp[i-1][k][1], dp[i-1][k][0] - prices[i])
我们发现数组中的 k 已经不会改变了,也就是说不需要记录 k 这个状态了:
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
理由:可以认为k和k-1一样,因为它是正无穷。
k=1是因为只能从-price跳到1,只有一次机会,控制了从0到1的次数,所以k没有用了,
k=+infinity,无论跳多少次都可以,所以k也没必要用。
作者:labuladong
链接:https://leetcode-cn.com/problems/two-sum/solution/yi-ge-fang-fa-tuan-mie-6-dao-gu-piao-wen-ti-by-l-3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。