代码随想录算法训练营第四十九天【动态规划part10】 | 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II
121. 买卖股票的最佳时机
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
求解思路:
动规五部曲
- 确定dp数组及其下标含义:使用一个二维数组dp[i][2],dp[i][0]代表持有股票的最大收益,dp[i][1]代表不持有股票的最大收益;注意“持有”不代表当天买入,可能是之前的某一天就买入了,“不持有”同理
- 确定递推公式:如果当天持有股票,则股票可能是之前就买好了,或者是当天买的,递推公式取两者较大值,即dp[i][0] = max(dp[i - 1][0], -prices[i]);如果当天不持有股票,则股票可能是之前就卖出了,也可能是当天才卖出,取两者较大值,即dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
- dp数组的初始化:dp[0][0]表示第0天持有股票,dp[0][0] -= prices[0];dp[0][1]表示第0天不持有股票,dp[0][1] = 0
- 确定遍历顺序:从前向后
- 举例推导dp数组:以[7,1,5,3,6,4]为例,dp数组状态如下
代码:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.size() == 0) return 0;
vector<vector<int>> dp(prices.size(),vector<int>(2));
// 0为当天持有该股票,1为当天不持有
dp[0][0] = -1 * prices[0];
dp[0][1] = 0;
for (int i = 1; i < prices.size(); i++){
// 当天持有股票,可能是之前买的,可能是今天买的
dp[i][0] = max(dp[i-1][0], -1 * prices[i]);
// 当天未持有股票,可能是之前卖了,也可能是今天卖了
dp[i][1] = max(dp[i-1][1], prices[i] + dp[i-1][0]);
}
return dp[prices.size()-1][1];
}
};
122.买卖股票的最佳时机II
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
求解思路:
和前一题唯一不一样的地方在于当天持有股票的所得金额,即dp[i][0]的递推公式
如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来:第i-1天就持有股票,则保持现状,即dp[i][0] = dp[i-1][0];第i天买入股票,则所得现金为昨天不持有股票的现金减去今天的股票价格,即 dp[i - 1][1] - prices[i]
代码:
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(prices.size(), vector<int>(2,0));
dp[0][0] = -prices[0];
dp[0][1] = 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][1], dp[i-1][0] + prices[i]);
}
return dp[prices.size()-1][1];
}
};