题目描述
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
解题思路
这道题和121题一样也是一道用动态规划解决的股票问题(刻yan吸fei股票问题基本都能用动态规划解决)。这道题相对于121题和122题难点在于状态的确定,虽然122题是可以多次买入,但实际上它的状态也是和121题一样今天是持有股票还是不持有,只是相对于121题来说我持有的时候可以是和昨天一样持有也可以是在昨天不持有股票今天买入。而121题限制了只能一次买入持有股票的时候要不是和昨天一样持有,要不就是昨天以前没有任何操作今天买入。而123题限制了买入的天数,最多完成两笔交易代表了三种情况:
- 我全程不做任何操作,不买入也不卖出
- 我买入卖出一次
- 我买入卖出两次
所以状态还是持有或者不持有,这里最好不要用买入卖出作为状态,非常误导自己,导致写状态转移方程会写错。但是状态里面要体现题目对次数的限制,那我就需要将三种次数情况和两种状态结合起来形成这道题的最终状态:
1.不做任何操作 状态数字0
2.第一次持有股票 状态数字1
3.第一次不持有股票 状态数字2
4.第二次持有股票 状态数字3
5.第二次不持有股票 状态数字4
状态转移方程:
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]);//第二次不持有
class Solution {
public int maxProfit(int[] prices) {
if(prices.length == 0) return 0;
int dp[][] = new int[prices.length][5];
dp[0][0] = 0;//不做任何操作
dp[0][1] = -prices[0];//第一次持有股票
dp[0][2] = 0;//第一次不持有股票
dp[0][3] = -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 dp[prices.length-1][4];
}
}