● 309.最佳买卖股票时机含冷冻期
多加条件:卖出之后有一天冷冻期不能买入,即卖出之后至少隔一天才能再买入。
要搞清楚每一天有什么状态:持有股票(已买入)、不持有股票(已卖出)。不持有股票可能是今天当天卖掉了,变成了不持有状态;也有可能是昨天卖掉了,所以今天是冷冻期,不能买入股票;还有可能是前天以及之前就卖掉了,所以今天是冷冻期之后(不包含)还未买入股票的日子。所以不持有股票还应该分为3种情况:今天卖掉、昨天卖掉、前天以及之前卖掉,数组应该是设置为dp[][4]。这4种情况是包含了所有的状态了的,顺序地组成了买入再卖出然后经过冷冻期的一个周期。
1.dp数组含义。
2.递推公式。4种情况是有些麻烦,今天的每一个情况,都要考虑前一天有没有可能是4种情况的一种,所以有16种组合,筛选后公式如下:
今天持有股票,有可能前一天持有,有可能前一天的昨天卖掉了,有可能前一天的前天以前卖掉了,不可能前一天当天卖掉,所以dp[i][0]=max(dp[i-1][0],max(dp[i-1][2],dp[i-1][3])-prices[i]);
今天当天卖掉了股票,只有可能前一天还持有股票。dp[i][1]=dp[i-1][0]+prices[i];
今天是冷冻期,只有可能前一天当天卖掉了股票。dp[i][2]=dp[i-1][1];
今天是冷冻期之后的日子,前一天可能是冷冻期,或者也是冷冻期之后的日子。所以dp[i][3]=max(dp[i-1][2],dp[i-1][3]);
这里的前一天指i-1坐标(第i天的前一天),昨天、前天指每个dp[i]的4的元素含义。
下面是代码随想录给出的状态转移图。卖出状态就是冷冻期之后的日子,这个图就概括了上面的递推过程。
这4个公式还可以化简,变成2个或者3个状态来递推也正确。
3.初始化。只有持有股票状态初始化为-prices[0],其他3种都是不持有股票状态,所以初始化为0.
4.遍历顺序。从左到右。
5.打印。
代码。最后的状态是手上没有股票,所以得取未持有股票的3种状态的最大值。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
vector<vector<int>> dp(n,vector<int>(4,0));
dp[0][0]=-prices[0];
for(int i=1;i<prices.size();++i){
dp[i][0]=max(dp[i-1][0],max(dp[i-1][2],dp[i-1][3])-prices[i]);
dp[i][1]=dp[i-1][0]+prices[i];
dp[i][2]=dp[i-1][1];
dp[i][3]=max(dp[i-1][2],dp[i-1][3]);
}
return max(max(dp[n-1][1],dp[n-1][2]),dp[n-1][3]);
}
};
● 714.买卖股票的最佳时机含手续费
题目与122.买卖股票的最佳时机II相比 ,就是加了一个手续费的问题,那么完成一次买卖,可以是卖一次就减去一次手续费,即最大金额dp[i][1]减去手续费fee;也可以是买一次就减去一次手续费,这样的话注意初始化dp[0][0]是买一次,要减去一个fee。
代码。卖出扣手续费:
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int n=prices.size();
vector<vector<int>> dp(n,vector<int>(2,0));//2种状态
dp[0][0]=-prices[0];
for(int i=1;i<prices.size();++i){
dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i]);
dp[i][1]=max(dp[i-1][0]+prices[i]-fee,dp[i-1][1]);
}
return dp[n-1][1];
}
};
买入扣手续费:
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int n=prices.size();
vector<vector<int>> dp(n,vector<int>(2,0));//2种状态
dp[0][0]=-prices[0]-fee;
for(int i=1;i<prices.size();++i){
dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i]-fee);
dp[i][1]=max(dp[i-1][0]+prices[i],dp[i-1][1]);
}
return dp[n-1][1];
}
};