给定一个数组,它的第 **
i
个元素是一支给定的股票在第i
**天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
**注意:**你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
按照题目描述每天的操作状态可以分为五个状态
0:没有操作
1:第一天持有股票
2:第一天不持有股票
3:第二天持有股票
4:第二天不持有股票
动规五部曲:
dp[i][j]表示第i天的0-4个中的j状态下最大金额
dp[i][1]的状态下有两种可能:
第i天买入股票:dp[i][1]=dp[i-1][0]-prices[i]
第i-1天买入股票,第i天保持:dp[i][1]=dp[i-1][1]
综上,dp[i][1]=max(dp[i-1][0]-prices[i],dp[i][1]=dp[i-1][1] )
dp[i][2]的状态下有两种可能:
第i天不持有股票:dp[i][2]=dp[i-1][1]+prices[i];
第i-1天不持有,第i天保持:dp[i][2]=dp[i-1][2];
综上,dp[i][2]=max(dp[i][2]=dp[i-1][1]+prices[i], dp[i][2]=dp[i-1][2])
dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i]);
dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[0]);
dp[0][1]=-prices[0]
dp[0][3]=-prices[0]
其他下标被设置为0即可
因为后一个状态需要由前一个状态推导得出,所以需要从前向后遍历
举例推导dp数组
prices=[1 2 3 4 5]
dp[i][0]=[0 0 0 0 0]
dp[i][1]=[-1 -1 -1 -1 -1]
dp[i][2]=[0 1 2 3 4]
dp[i][3]=[-1 -1 -1 -1 -1]
dp[i][4]=[0 1 2 3 4]
class Solution {
public int maxProfit(int[] prices) {
if(prices==null||prices.length==0){
return 0;
}
int[][] dp=new int[prices.length][5];
dp[0][1]=-prices[0];
dp[0][3]=-prices[0];
for(int i=1;i<prices.length;i++){
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];
}
}
给定一个整数数组
prices
,它的第 **i
个元素prices[i]
是一支给定的股票在第i
**天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。
**注意:**你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
输入:k = 2, prices = [2,4,1]
输出:2
解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
这道题和上一题很类似不同之处就是上一道题明确告诉了2笔交易所以状态为5中,本题给出k比交易状态即为2*k+1,所以我们只需要在上一题的基础上再嵌套一层循环又来遍历j
动规五部曲
dp[i][j]表示第i天j状态下,所剩下最大金额为dp[i][j]
dp[i][1]表示第i天买入股票的状态
所以dp[i][1]状态可能存在两种操作:
①第i天买入股票:dp[i][1]=dp[i-1][0]-peices[i];
②第i-1天买入股票,第i天保持状态:dp[i][1]=dp[i-1][1]
dp[i][1]=max(dp[i-1][0]-peices[i], dp[i][1]=dp[i-1][1])
dp[i-2]状态同样也存在以下两种操作:
①第i天卖出股票 dp[i][2]=dp[i-1][1]+prices[i]
②第i-1天卖出股票,第i天保持 dp[i][2]=dp[i-1][2]
dp[i][2]=max(dp[i-1][1]+prices[i], dp[i][2]=dp[i-1][2])
每次买入状态都将dp[i][j]=-prices[0]
从前往后遍历
class Solution {
public int maxProfit(int k, int[] prices) {
if(prices==null||prices.length==0){
return 0;
}
int[][] dp=new int[prices.length][2*k+1];
for(int j=1;j<2*k;j+=2){
dp[0][j]=-prices[0];
}
for(int i=1;i<prices.length;i++){
for(int j=0;j<2*k-1;j+=2){
//第一天的操作
dp[i][j+1]=Math.max(dp[i-1][j+1],dp[i-1][j]-prices[i]);
//第二天的操作
dp[i][j+2]=Math.max(dp[i-1][j+2],dp[i-1][j+1]+prices[i]);
}
}
return dp[prices.length-1][2*k];
}
}