一、LeetCode123. 买卖股票的最佳时机 III
因为股票至多能买卖两次,所以每一天的股票我们可以有五个状态:不处理、第一次买卖、第二次买卖。
即:dp[i][0]表示第i天股票不做处理时的状态。
dp[i][1]表示第i天保持第一次买入时的状态。
dp[i][2]表示第i天保持第一次卖出时的状态。
dp[i][3]表示第i天保持第二次买入时的状态。
dp[i][4]表示第i天保持第二次卖出时的状态。
1、dp数组及下标含义:dp[i][j] 表示第i天股票买卖为j时手里现金的最大值。
2、递推公式:
(1)股票不做任何处理时当天的金额就是前一天金额,dp[i][0] = dp[i - 1][0];
(2)第i天保持第一次买入时,dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1]);
(3)第i天保持第一次卖出时,dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2]);
(4)第i天保持第二次买入时,dp[i][3] =max(dp[i - 1][2] - prices[i], dp[i - 1][3]);
(5)第i天保持第二次卖出时,dp[i][4] = max(dp[i - 1[3] + prices[i], dp[i - 1][4]);
3、初始化:
dp[0][0] = 0;
dp[0][1] = -prices[0];第一次买入时手中的金额。
dp[0][2] = 0;第一次卖出。
dp[0][3] = -prices[0];第二次买入。
dp[0][4] = 0;
4、遍历顺序,因为dp[i] 由dp[i -1]推导出来,所以从i = 1开始从小到大去遍历。
5、打印dp数组。
代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>>dp(prices.size(), vector<int>(5));
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], 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];
}
};
二、LeetCode188. 买卖股票的最佳时机 IV
题目链接:188. 买卖股票的最佳时机 IV
这道题的解法跟上道题类似,只不过需要将能买卖两天的所有状态变成能买卖k天的所有状态即可。
两次买卖的状态由22+1种,而买卖k次的状态共有2k+1种。
所以初始化时我们需要:
for(int i = 0; i <= 2 * k; i++) {
if(i % 2 == 0) dp[0][i] = 0;
else dp[0][i] = -prices[0];
}
递推公式则是:
if(j == 0) dp[i][j] = dp[i - 1][j];
else {
if(j % 2 == 1) {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
} else {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + prices[i]);
}
}
代码如下:
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
vector<vector<int>>dp(prices.size(), vector<int>(2 * k + 1));//有2 * k + 1种状态
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++) {
if(j == 0) dp[i][j] = dp[i - 1][j];
else {
if(j % 2 == 1) {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
} else {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + prices[i]);
}
}
}
}
// for(int i = 0; i < prices.size(); i++) {
// for(int j = 0; j <= 2 * k; j++) {
// cout<<dp[i][j]<<" ";
// }
// cout<<endl;
// }
return dp[prices.size() - 1][2 * k];
}
};
总结
如果不看题解感觉还是很困难的!