123.买卖股票的最佳时机III
class Solution {
public:int maxProfit(vector<int>& prices) {if(prices.size() == 0) return 0;vector<vector<int>> dp(prices.size(), vector<int>(5,0));//dp[i][j] 表示根据j的方法数下,第i天时候最大的金额量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];}
};
具体思路:
既然是2次买卖,则根据状态的延续,会存在上述5个状态(虽然关于0状态没必要单独写,只是为了好理解)。则依次解释每个状态计算:
dp[i][0] = dp[i-1][0] :
第i天不作操作当然是由前面不作操作的状态延续来;
dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i]):
第i天第一次持有股票的状态来源要么是前i-1天就已经持有股票的状态,要么则是第i天买入股票,那么此状态只能通过前i-1天无操作才能得来。
dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i]);
第i天第一次卖出的状态要么是在i-1天之前已经卖出了,而这个状态一直持续到现在,或者是选择第i天将股票卖出,而当天卖出前提是我已经持有此股票,则状态只能是由i-1天以前一直持有此股票,即状态1的情况下,再卖出此股票即加上当前时刻股票价格即可。
后面其实一回事,只是3需要注意的一点就是,因为题目说每次必须卖完才能买卖下一次股票,则第2次购买股票,即状态码为3,需要再dp[i-1][2],即上一次操作已经完成的状态下进行。后面都一样了。
还有关于dp数组初始化的问题,行数如何选取这一块,size()是否需要+1,得看递推中是否存在需要多定义一行这一情况,比较常见的就是前几个数的可以满足获得dp值的这一情况,这种可能需要定义前0个数的状态,则这种就需要初始化 size()+1.
188.买卖股票的最佳时机IV
class Solution {
public:int maxProfit(int k, vector<int>& prices) {vector<vector<int>> dp(prices.size(),vector<int>(2*k+1,0));for(int j = 1; j < 2*k; j += 2){dp[0][j] = -prices[0];}// dp[0][0] = 0;// dp[0][1] = -prices[0];//持有股票的状态// dp[0][2] = 0;//卖出股票的状态for(int j = 1; j < prices.size(); j++){for(int i = 0; i < 2*k; i += 2){dp[j][i+1] = max(dp[j-1][i+1],dp[j-1][i] - prices[j]);//持有dp[j][i+2] = max(dp[j-1][i+2], dp[j-1][i+1] + prices[j]);//卖出}}return dp[prices.size()-1][2*k];}
};
具体思路:
因为是k此买卖,则就是上述题目的变种,需要在买卖状态添加一个0无操作的状态,则总共K次买卖有 2*k+1种状态,别忘了对第一天所有状态都要初始化,这个我忘了!
其次后面就是对所有状态进行更新,没啥好讲的,跟上面一样,只是抽象化了,还有最后return的范围注意看,因为初始化是2k+1,则最终是为了获得下标为2k的数据,因为多的1是0下标。