dp[i][k][0 or 1] 0 <= i <= n - 1, 1 <= k <= K,n 为天数,大 K 为交易数的上限,0 和 1 代表是否持有股票
比如
dp[2][3][0]
的含义:今天是第二天,我现在手上没有持有股票,至今最多进行 3 次交易
状态转移方程
base case:
dp[-1][...][0] = dp[...][0][0] = 0
dp[-1][...][1] = dp[...][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])
你买股票,初始的「状态」是什么?应该是从第 0 天开始,而且还没有进行过买卖,所以最大交易次数限制
k
应该是max_k
;而随着「状态」的推移,你会进行交易,那么交易次数上限k
应该不断减少,这样一想,k = max_k, k--
的方式是比较合乎实际场景的。
class Solution {
public int maxProfit(int[] prices) {
int max_k = 2;//限制最大交易次数2
int dp[][][]=new int[prices.length+1][max_k+1][2];
//在第i天买卖股票的利润,0表示手中无股票,1表示手中有股票
for(int i=0;i<=max_k;i++){
dp[0][i][0]=0;
dp[0][i][1]=-prices[0];
}
int max=0;
for(int i=1;i<=prices.length;i++){
for(int k=1;k<=max_k;k++){
dp[i][k][1]=Math.max(dp[i-1][k-1][0]-prices[i-1],dp[i-1][k][1]);
dp[i][k][0]=Math.max(dp[i-1][k][0],dp[i-1][k][1]+prices[i-1]);
max=Math.max(max,dp[i][k][0]);
}
}
return max;
}
}
考虑冷冻期,且交易无限制
class Solution {
public int maxProfit(int[] prices) {
int dp[][]=new int[prices.length+1][2];//在第i天买卖股票的利润,0表示手中无股票,1表示手中有股票
dp[0][0]=0;dp[0][1]=-prices[0];
int max=0;
for(int i=1;i<=prices.length;i++){
if(i>=3)//第3天即以后,只能买大前天卖出的股票
dp[i][1]=Math.max(dp[i-2][0]-prices[i-1],dp[i-1][1]);
else
dp[i][1]=Math.max(dp[i-1][0]-prices[i-1],dp[i-1][1]);
dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i-1]);
max=Math.max(max,dp[i][0]);
}
return max;
}
}