123. 买卖股票的最佳时机III
题意要求最多可以完成两笔交易,也就是说可以不进行交易、只进行一次交易、进行两次交易这三种情况。还要去不能同时参与多笔交易,在再次购买前出售掉之前的股票。
动规五部曲:
(1)确定dp数组及下标的含义:使用二维数组,dp[0][0] —— 不进行交易,dp[i][1] —— 只进行一次交易时持有股票所能获取的最大利润是dp[i][1],dp[i][2] —— 只进行一次交易时不持有股票所能获取的最大利润是dp[i][2],dp[i][3] —— 进行两次交易时持有股票所能获取的最大利润是dp[i][3],dp[i][4] —— 进行两次交易时不持有股票所能获取的最大利润是dp[i][1]。
(2)确定递推公式: 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]);
(3)对dp数组初始化: 不进行交易时所获取的最大利润是0,dp[0][0] = 0,dp[0][1] = -prices[0], dp[0][2] = 0,dp[0][3] = -prices[0],dp[0][4] = 0。
(4)确定遍历顺序: 后一个状态由前一个状态推导出来,从前往后遍历。
(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][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
其实是上一道题目的推广吧。
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 == 1){
dp[0][i] = -prices[0];
}
}
for (int i = 1; i < prices.size(); i++){
for (int j = 0; j < 2 * k - 1; 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];
}
};
加油啊~