/**
* dp[n][k][2]
* 从最典型的开始出发,n:天数,k:可以操作的次数,2:0-不持有股票;1-持有股票
* dp[5][2][0]:一共有5天,执行2次操作,当前不持有股票
* 状态转移方程: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])
* dp[i-1][0][0]:k=0,不允许交易 dp[i-1][0][0]=0;
* k均为1,消掉
* 状态转移方程:dp[i][0] = max(dp[i-1][0],dp[i-1][1]+prices[i])
* dp[i][1] = max(dp[i-1][1],-prices[i])
*
* 注意:i=0的时候,数组越界,分开讨论
* dp[i][0] = max(dp[-1][0],dp[-1][1]+prices[i]) = max(0,-无穷[不可能持有股票]) = 0
* dp[i][1] = max(dp[i-1][1],-prices[i]) = max(-无穷,-prices[i]) = -prices[i]
*/
public class Code03_MaxProfit01 {
public static void main(String[] args) {
int []prices = new int[]{7,1,5,3,6,4};
int res = maxProfit(prices);
System.out.println(res);
}
public static int maxProfit(int[] prices) {
if (prices.length==0 || prices==null) return 0;
int n = prices.length;
int dp[][] = new int[n][2];
for (int i=0;i<n;i++) {
if (i-1==-1) {
dp[i][0] = 0;
dp[i][1] = -prices[i];
continue;
}
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]+prices[i]);
dp[i][1] = Math.max(dp[i-1][1],-prices[i]);
}
return dp[n-1][0];
}
}
直接用一个变量代替数组,改进版代码如下:
public static int maxProfit2(int[] prices) {
if (prices.length==0 || prices==null) return 0;
int n = prices.length;
// base case: dp[-1][0] = 0, dp[-1][1] = -infinity
int dp_i_0 = 0, dp_i_1 = Integer.MIN_VALUE;
for (int i=0;i<n;i++) {
dp_i_0 = Math.max(dp_i_0,dp_i_1+prices[i]);
dp_i_1 = Math.max(dp_i_1,-prices[i]);
}
return dp_i_0;
}