121. 买卖股票的最佳时机
**1.dp数组含义:**dp[i][0]、dp[i][1]分别代表第i天,不持有股票和持有股票获得的最大价值;
2.递推公式:
不持有股票:dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
两种情况,1. 第i-1天就没有持有股票,第i天不操作,所以延续不持有的价值;2. 第i-1天持有股票了,到第i天卖出,导致第i天不持有,所以是 dp[i-1][1]+prices[i]。两种情况取最大值。
持有股票:dp[i][1] = max(dp[i-1][1], -prices[i])
两种情况,1. 第i-1天就持有股票,第i天不操作,所以延续持有的价值;2. 第i-1天不持有股票,到第i天买入,导致第i天持有,所以是 -prices[i]。两种情况取最大值。
**3.初始化:**只需初始化第0天持有或不持有手中的价值,分别是-prices[0]和0
**4.遍历顺序:**顺序遍历,从1到尾索引;
注:由于递推只用到了dp[i-1],所以可以只创建大小为2*2的数组,滚动更新第i-1天和第i天即可,通过取模实现。
cpp
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(2, vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i=1;i<prices.size();i++){
dp[i%2][0] = max(dp[(i-1)%2][0], dp[(i-1)%2][1]+prices[i]);
dp[i%2][1] = max(dp[(i-1)%2][1], -prices[i]);
}
return dp[(prices.size()-1) %2][0];
}
};
122.买卖股票的最佳时机II
和上一题的区别在于:本题可以多次买卖,因此对于第i天持有股票了来说,不一定是第几次持有,所以买入第i天股票时手里的钱不确定是不是0,所以持有股票的递推公式需要改为
cpp
dp[i][1] = max(dp[i-1][1], -prices[i]);
应改为:
cpp
dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i]);
cpp
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(2, vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i=1;i<prices.size();i++){
dp[i%2][0] = max(dp[(i-1)%2][0], dp[(i-1)%2][1]+prices[i]);
dp[i%2][1] = max(dp[(i-1)%2][1], dp[(i-1)%2][0]-prices[i]);
}
return dp[(prices.size()-1) %2][0];
}
};
123.买卖股票的最佳时机III
和前两题区别在于,本题最多只能买卖两次,所以全部覆盖状态比较多,需要分成dp[i][0]、dp[i][1]、dp[i][2]、dp[i][3]、dp[i][4],分别代表第i天不操作、第一次持有、第一次不持有、第二次持有、第二次不持有;
**递推公式:**dp[i][0]延续即可;dp[i][1]由第i-1天的1延续而来,或者0买入;dp[i][2]由第i-1天的2延续而来,或者1卖出;dp[i][3]由第i-1天的3延续而来,或者2买入;dp[i][4]由第i-1天的4延续而来,或者3卖出;
**初始化:**只需要考虑第0天的五种状态,只有持有的时候才会不是0,呈现出负的第一天股票价格,其余都相当于同一天多次买卖,不持有股票,即为0;
cpp
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(2, vector<int>(5,0));
dp[0][1] = -prices[0];//第一次持有
dp[0][3] = -prices[0];//第二次持有
for(int i=1;i<prices.size();i++){
dp[i%2][0] = dp[(i-1)%2][0];
dp[i%2][1] = max(dp[(i-1)%2][1], dp[(i-1)%2][0]-prices[i]);
dp[i%2][2] = max(dp[(i-1)%2][2], dp[(i-1)%2][1]+prices[i]);
dp[i%2][3] = max(dp[(i-1)%2][3], dp[(i-1)%2][2]-prices[i]);
dp[i%2][4] = max(dp[(i-1)%2][4], dp[(i-1)%2][3]+prices[i]);
}
return dp[(prices.size()-1) %2][4];
}
};