文章链接:121. 买卖股票的最佳时机122.买卖股票的最佳时机II123.买卖股票的最佳时机III

视频链接:121. 买卖股票的最佳时机122.买卖股票的最佳时机II123.买卖股票的最佳时机III

题目链接:121. 买卖股票的最佳时机122.买卖股票的最佳时机II123.买卖股票的最佳时机III


121.买卖股票的最佳时机

思路:

1.dp数组的含义:dp[i][0]表示持有股票时的最大金额,dp[i][1]表示不持有股票时的最大金额。

2.递推公式

dp[i][0] = max(dp[i - 1][0], -prices[i]); // 第i - 1天 持有(即不是第i天买的) 或者  第i天买入

dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);  // 第i - 1天 不持有(即不是第i天卖的) 或者 第i天卖出

3.dp数组初始化

dp[0][0] = -prices[0];

dp[0][1] = 0;


class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (prices.size() == 0) return 0;
        vector<vector<int>> dp(prices.size() + 1, vector<int> (3, 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], -prices[i]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
        }
        return dp[prices.size() - 1][1];
    }
};


122.买卖股票的最佳时机II

思路:

与上一题的区别本题股票可以买卖多次;

与上一题只有递推公式不同

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]);

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        vector<vector<int>> dp(len, vector<int>(2, 0));
        dp[0][0] -= prices[0];
        dp[0][1] = 0;
        for (int i = 1; i < len; i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]); 
            // 注意这里是和121. 买卖股票的最佳时机唯一不同的地方。
            
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
        }
        return dp[len - 1][1];
    }
};


123.买卖股票的最佳时机III

思路:

与上两题的区别至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。

1.dp数组的含义

  1. 没有操作 (其实我们也可以不设置这个状态)
  2. 第一次持有股票
  3. 第一次不持有股票
  4. 第二次持有股票
  5. 第二次不持有股票

dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。

2.递推公式

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]);

            

3.dp数组初始化

dp[0][0] = 0;

dp[0][1] = -prices[0];

dp[0][2] = 0; // 第一天买入和卖出

dp[0][3] = -prices[0]; // 第一天买入->卖出 ->买入

dp[0][4] = 0; // 第一天买入->卖出 ->买入->卖出

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[0][1] = -prices[0];
        dp[0][3] = -prices[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]; // 直接返回第4中状态即可(第2种状态包含在第4种中)
    }
};