123.买卖股票的最佳时机III
解题思路
这题的区别在于至多买卖两次
1. dp[i][0] 第i天不操作 dp[i][1]第一次持有股票(可能延续了前一次买卖的状态) dp[i][2]第一次不持股票 dp[i][3] 第二次持有 dp[i][4]第二次不持有
2.递推公式
dp[i][0] = dp[i-1][0] 不操作是由前一天推得而来
第一次持有 dp[i][1] = max( dp[i-1][1] , dp[i-1][0]-price[i]) 可以由前一天持有推得,也可以由前一天不操作推得
第一次不持有状态 dp[i][2] = max( dp[i-1][2], dp[i-1][1]+price[i]) 可以由前一天不持有,也可以由前一天持有时卖掉推得而来
第二次持有 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[i]) 可以由前一天第二次不持有,和前一天第二次卖出
3.初始化
dp[0][0] =0;
dp[0][1] = -prices[0];
dp[0][2] = 0;
dp[0][3] = -prices[0]; //理解为先买入再卖,再买
dp[0][4] = 0;
4.遍历顺序
由前往后
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(prices.size(),vector<int>(5,0));
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.size(); i++)
{
dp[i][0] = dp[i-1][0];
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] );
dp[i][4] = max( dp[i-1][4], dp[i-1][3] + prices[i] );
}
return dp[prices.size()-1][4];
}
};
188.买卖股票的最佳时机IV
解题思路
这题的区别是至多买卖k次
1.dp[price.size()][2k+1] 第i天 的 第k次买卖的最大现金
2.对着|||的递推公式,找规律即可,将2次变成一个循环
写出一次买卖的操作
dp[i][j+1] = max(dp[i-1][j+1], dp[i-1][j] - prices[i]); //持股
dp[i][j+2] = max(dp[i-1][j+2], dp[i-1][j+1] + prices[i]); //不持股
3.初始化
偶数k -price[i]
奇数k 0
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
vector<vector<int>> dp(prices.size(),vector<int>(2*k+1,0));
for(int i=0 ; i<=2*k;i++)
{
if(i%2==0) dp[0][i] = 0;
else dp[0][i] = -prices[0];
}
for(int i =1 ; i<prices.size() ; i++)
{
for(int j=0 ; j<2*k ; j+=2)
{
dp[i][j+1] = max(dp[i-1][j+1], dp[i-1][j] - prices[i]); //持股
dp[i][j+2] = max(dp[i-1][j+2], dp[i-1][j+1] + prices[i]); //不持股
}
}
return dp[prices.size()-1][2*k];
}
};
动态规划的第二个维度可以用一个for循环来控制
收获
动态规划悟到了