题目来源
123. 买卖股票的最佳时机 III
一天一共就有5个状态
不操作
第一次持有股票
第一次不持有股票
第二次持有股票
第二次不持有股票
达到dp[i][1]状态,有两个具体操作:
操作一:第i天买入股票了,那么dp[i][1] = dp[i-1][0] - prices[i]
操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]
一定是选最大的,所以 dp[i][1] = Math.max(dp[i - 1][1],- prices[i]);
同理dp[i][2]也有两个操作:
操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]
所以dp[i][2] = Math.max(dp[i - 1][1] + prices[i], dp[i - 1][2])
同理可推出剩下状态部分:
dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
第0天做第一次买入的操作,dp[0][1] = -prices[0];
第0天做第一次卖出的操作,这个初始值应该是多少呢?
此时还没有买入,怎么就卖出呢? 其实大家可以理解当天买入,当天卖出,所以dp[0][2] = 0;
第二次买入依赖于第一次卖出的状态,其实相当于第0天第一次买入了,第一次卖出了,然后再买入一次(第二次买入),那么现在手头上没有现金,只要买入,现金就做相应的减少。
所以第二次买入操作,初始化为:dp[0][3] = -prices[0];
同理第二次卖出初始化dp[0][4] = 0;
从递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]的数值。
以输入[1,2,3,4,5]为例

代码实现
class Solution {public int maxProfit(int[] prices) {if(prices == null || prices.length == 0){return 0;}int[][] dp = new int[prices.length][5];dp[0][1] = -prices[0];dp[0][2] = 0;dp[0][3] = -prices[0];dp[0][4] = 0;for(int i = 1;idp[i][1] = Math.max(dp[i-1][1],-prices[i]); //第一次持有dp[i][2] = Math.max(dp[i-1][2],dp[i][1]+prices[i]); //第一次不持有dp[i][3] = Math.max(dp[i-1][3],dp[i][2]-prices[i]); //第二次持有dp[i][4] = Math.max(dp[i-1][4],dp[i][3]+prices[i]); //第二次不持有}return dp[prices.length-1][4];}
}
