给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
分析:这道题相较于正篇,多了个冷冻期,我认为难度提升了不少,重点是要对这其中的弯弯绕绕要弄清楚。
有了冷冻期之后,状态就变成了4种,对这4种要特别清晰,不能被绕晕!
状态1:持有股票或刚买入股票
状态2:卖出股票的第一天 //说明:既然说是第一天,那么今天是必然会卖股票的,递推公式中不用和前一天进行比较
状态3:无票在手 //此状态为卖出股票的第二天之后或是一直未持有股票的状态
状态4:冷冻期 //说明:冷冻期也是一个固定状态而不是递推状态,它是一个确定值而不是比较值
状态转移:
状态1: 有3个状态可以转到状态1:
1.不动
2.昨天是冷冻期,可买入股票
3.昨天是状态3,即自由状态,可买入股票
那么递推公式为:
dp[i][0]=Math.max(dp[i-1][0],Math.max(dp[i-1][3]-prices[i],dp[i-1][4]-prices[i]))
状态2:只有状态1可以得到状态1,且其为确定值:
dp[i][1]=dp[i-1][0]+prices[i]
状态3:有2个状态可以转到状态3:
1.不动
2.冷冻期转入
则递推公式为:
dp[i][3]=Math.max(dp[i-1][3],dp[i-1][4])
状态4:只有前一天的状态2可以得到状态1,故其为确定值:
dp[i][4]=dp[i-1][2]
初值:与之前相同,直接将第一天的买入设为-prices[i]即可
返回值:由于状态3的更新会晚一天,所以要取状态2与状态3的最大值;
参考代码:
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][4];
dp[0][0]=-prices[0];
for(int i=1;i
dp[i][1]=dp[i-1][0]+prices[i];
dp[i][2]=Math.max(dp[i-1][1],dp[i-1][2]);
dp[i][3]=dp[i-1][1];
}
return Math.max(dp[prices.length-1][1],dp[prices.length-1][2]);
}
