给定一个整数数组
prices,它的第 **i个元素prices[i]是一支给定的股票在第i**天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。
这一道题就是一个比较难的动态规划题,最大的难点就是初始化,其次就是做题时一定要对交易充分理解。
思路:
- 定义dp数组 dp[n][k+1][2], 该数组dp含义为 (n:天数 k+1:交易次数 2代表是否持股(0:没有持股;1:持股)该数组的值就是代表在第n天交易了k次持有(dp[n][k][1])或者没有持有股票(dp[n][k][0])的最大值。
- 定义状态方程,这个就是很关键的步骤了,首先你一定要自己清楚,你自己定义一次交易的概念。到底是买的时候就是交易一次,还是卖的时候才是交易一次。
买的时候就是代表交易一次:
dp[i][k][0] = Math.max(dp[i-1][k][0],dp[i-1][k][1] + prices[i]
dp[i][k][1] = Math.max(dp[i-1][k][1],dp[i-1][k-1] - prices[i]
卖的时候就是代表交易一次:
dp[i][k][0] = Math.max(dp[i-1][k][0],dp[i-1][k-1][1] + prices[i]
dp[i][k][1] = Math.max(dp[i-1][k][1],dp[i-1][k] - prices[i]
3.初始化,也是本题最难的地方,同动态规划一样也是需要根据你自己对于交易的定义分开讨论。
- 首先考虑第零天的情况:dp[0][k][0] = 0;第零天做了k笔交易不持股,因为当天股票价格一样,无论做了多少笔交易,最大值都为零。dp[0][k][1] = -prices[0];第零天做了k笔交易持股,同样因为价格一样,持股那么就是-pricesp[0];
- 其次就是考虑每天交易0次的情况:dp[i][0][0] = 0;第i天做了0笔交易不持股,如果做了零笔交易且不持股那么就没有任何操作,那么最大值就是为零;dp[i][0][1]第i天交易零次持股,这就涉及到了你对于交易的定义,如果你是考虑买为一次交易的话,那么就代表没有买股票,与持股互相矛盾,但是优先考虑没有买股票,无论是否持股,该值应为0;如果你是考虑卖为一次交易的话,那么就代表你可能是今天买的或者你是昨天就持有该股票的且都是没有卖过的那么就为Math.max(dp[i-1][0][1],dp[i-1][0][0] - price[i]) 注意 dp[i-1][0][0]前面已经说过了始终为零,自己可以简写一下。
总结:从交易的定义来看代码,如果你希望少写代码那么你就可以设买就代表一次交易,如果你希望能更好的理解该题意,或者理解有点吃力,你就可以以卖就代表一次交易。