123 买卖股票的最佳时机 III
题目链接:123
思路:可以买入买出两次,因此定义5种状态:
- 0: 无操作,即一次都没买过。
- 1: 第一次持有(第一次买入)。
- 2: 第一次不持有(第一次卖出后,第二次买入前)。
- 3: 第二次持有(第二次买入)。
- 4: 第二次不持有(第二次卖出后)。
然后对每种状态进行分析:
- 今天无操作,则昨天一定无操作,继承
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])
。
代码:
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.back()[4];
}
};
188 买卖股票的最佳时机 IV
题目链接:188
思路:与123 买卖股票的最佳时机 III类似,规定最多k次交易,可定义2*k+1
种状态;根据规律,
j>0
且j
为奇数时为买入状态,即dp[i][j]=dp[i-1][j],dp[i-1][j-1]-prices[i]
;- 当
j>0
且j
为偶数时为卖出状态,即dp[i][j]=dp[i-1][j],dp[i-1][j-1]+prices[i]
。
代码:
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
if (k == 0 || prices.size() == 0) return 0;
vector<vector<int>> dp(prices.size(), vector<int>(2*k+1));
for (int j=1; j<2*k+1; j+=2) {
dp[0][j] = -prices[0];
}
for (int i=1; i<prices.size(); i++) {
for (int j=1; j<2*k+1; j++) {
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]);
}
}
return dp.back()[2*k];
}
};