这道题如果延续前面买卖股票的思路,只用两个状态是不够的,需要四个状态:
dp数组定义
dp[i][0]:第i天第一次持有股票的最大金额;
dp[i][1]:第i天第一次不持有股票的最大金额;
dp[i][2]:第i天第二次持有股票的最大金额;
dp[i][3]:第i天第二次不持有股票的最大金额;
递推:
第i天第一次持有股票的最大金额是前一天的该状态和当前第一次买的最大值;
第i天第一次不持有股票的最大金额是前一天该状态和前一天第一次持有股票并今天卖出的最大值;
第i天第二次持有股票的最大金额是前一天该状态和当前第二次买的最大值;
第i天第二次不持有股票的最大金额是前一天该状态和前一天第二次持有并今天卖出的最大值。
详细代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
//动态dp数组记录四个状态
//dp[0]:第i天第一次持有股票的最大金额
//dp[1]:第i天第一次不持有股票的最大金额
//dp[2]:第i天第二次持有股票的最大金额
//dp[3]:第i天第二次不持有股票的最大金额
vector<vector<int>>dp(prices.size(),vector<int>(4,0));
dp[0][0]=-prices[0];
dp[0][2]=-prices[0];
for(int i=1;i<prices.size();i++){
dp[i][0]=max(dp[i-1][0],-prices[i]);
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]);
dp[i][2]=max(dp[i-1][2],dp[i-1][1]-prices[i]); //第一次交易结束才能第二次
dp[i][3]=max(dp[i-1][3],dp[i-1][2]+prices[i]);
}
return max(dp[prices.size()-1][1],dp[prices.size()-1][3]);
}
};
只需要增加一个0状态不操作,这样可以方便统一写递推公式,然后奇数就是持有,偶数就是不持有,类比上述的递推公式即可完成本题,依次对2k个状态进行赋值,详细代码如下:
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
//这道题是买卖股票3的进阶版,需要类比奇数状态是买,偶数状态是卖的思路
vector<vector<int>>dp(prices.size(),vector<int>(2*k+1,0));
for(int j=1;j<2*k+1;j+=2)
{
dp[0][j]=-prices[0];
}
for(int i=1;i<prices.size();i++)
{
for(int j=1;j<2*k+1;j+=2)
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]-prices[i]); //奇数买
dp[i][j+1]=max(dp[i-1][j+1],dp[i-1][j]+prices[i]);//偶数卖
}
}
return dp[prices.size()-1][2*k];
}
};