题意理解:
给定一个数组,它的第
i
个元素是一支给定的股票在第i
天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
这道题目的特殊之处在于,至多两次交易:
包含: 不交易、 交一次、 交易两次
这里为了便于理解对交易期间每个状态进行定义:五种状态
无操作:dp[i][0]
第一次持有:dp[i][1]
第一次不持有:dp[i][2]
第二次持有:dp[i][3]
第二次不持有:dp[i][4]
我们使用动态规划的思路进行求解。
解题思路:
(1)定义二维dp数组
无操作:dp[i][0] 第一次持有:dp[i][1] 第一次不持有:dp[i][2]
第二次持有:dp[i][3] 第二次不持有:dp[i][4]
(2)初始化
dp[0][0]=dp[0][2]=dp[0][4]=0
dp[0][1]=dp[0][3]=-prices[0]
(3)递推公式
dp[i][0]=dp[i-1][0]
dp[i][1]=max(延续上衣状态,买入)=max(dp[i-1][1],dp[i-1][0]-prices[i])
dp[i][2]=max(延续上一状态,卖出)=max(dp[i-1][2], dp[i-1][1]+prices[i])
dp[i][3]=max(延续上一状态,买入)=max(dp[i-1][3],dp[i-1][2]-prices[i]);
dp[i][4]=max(延续上一状态,卖出)=max(dp[i-1][4],dp[i-1][3]+prices[i])
1.解题
public int maxProfit(int[] prices) {
int[][] dp=new int[prices.length][5];
dp[0][0]=0;
dp[0][1]=-1*prices[0];
dp[0][2]=0;
dp[0][3]=-1*prices[0];
dp[0][4]=0;
for(int i=1;i<prices.length;i++){
dp[i][0]=dp[i-1][0];
dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);
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]);
}
return Math.max(dp[dp.length-1][0],Math.max(Math.max(dp[dp.length-1][1],dp[dp.length-1][2]),Math.max(dp[dp.length-1][3],dp[dp.length-1][4])));
}
2.分析
时间复杂度: O(n)
空间复杂度:O(5n)