文章链接: 188.买卖股票的最佳时机IV 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费

视频链接: 188.买卖股票的最佳时机IV 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费

题目链接: 188.买卖股票的最佳时机IV 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费


188.买卖股票的最佳时机IV

思路:

 123.买卖股票的最佳时机III的区别:要求买卖至多k次。

1.dp数组的含义

dp[i][j] :第i天的状态为j,所剩下的最大现金是dp[i][j]

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

除了0以外,偶数就是不持有,奇数就是持有

2.递推公式

// 记录一次买入和卖出
for (int j = 0; j <= 2 * k - 2; 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]);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

3.初始化

dp[0][j]当j为奇数的时候都初始化为 -prices[0];


class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if (prices.size() == 0) return 0;
        vector<vector<int>> dp(prices.size() + 1, vector<int> (2 * k + 2, 0));
        for (int j = 1; j <= 2 * k; j += 2) { // 初始化
            dp[0][j] = -prices[0];
        }
        for (int i = 1; i < prices.size(); i++) {
            for (int j = 0; j <= 2 * k - 2; 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];
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.



309.最佳买卖股票时机含冷冻期

思路:

1.dp数组的含义

dp[i][0] : (状态一)持有股票

dp[i][1] : (状态二)保持卖出股票的状态(两天前就卖出了股票,度过一天冷冻期。或者是前一天就是卖出股票状态,一直没操作)

dp[i][2] : (状态三)今天卖出股票

dp[i][3] : (状态四)冷冻期

注意:状态二、三之前的题目时合在一起的,但是这里需要分开。

2.递推公式

dp[i][0] 可由两种状态推出:前一天持有股票、当天卖出股票(前一天为状态二或四);

dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);

dp[i][1] 可由两种状态推出:前一天卖出股票、两天前就卖出了股票并度过一天冷冻期(即前一天是冷冻期);

dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);

dp[i][2] 可由前一天持有股票推出;

dp[i][2] = dp[i - 1][0] + prices[i];

dp[i][3] 可由前一天卖出股票推出;

dp[i][3] = dp[i - 1][2];

3.初始化dp数组

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

dp[0][1] = 0;

dp[0][2] = 0;

dp[0][3] = 0;


class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if (n == 0) return 0;
        vector<vector<int>> dp(n, vector<int>(4, 0));
        dp[0][0] -= prices[0]; 
        for (int i = 1; i < n; i++) {
            dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3] - prices[i], dp[i - 1][1] - prices[i]));
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
            dp[i][2] = dp[i - 1][0] + prices[i];
            dp[i][3] = dp[i - 1][2];
        }
        return max(dp[n - 1][3], max(dp[n - 1][1], dp[n - 1][2])); 
        // 股票没在手上有三种状态,取最大值
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.



714.买卖股票的最佳时机含手续费

思路:

 122.买卖股票的最佳时机II只有手续费的区别,只要在卖出时减去手续费即可。

注意:返回的值也与 122有区别,122题没有手续费,所以卖出时一定能比买入时利润大;

但该题有手续费,卖出和买入不一定谁的利润大。

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int n = prices.size();
        vector<vector<int>> dp(n, vector<int>(2, 0));
        dp[0][0] -= prices[0]; 
        for (int i = 1; i < n; 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] - fee); // 卖出(交手续费)
        }
        return max(dp[n - 1][0], dp[n - 1][1]); // 也有区别
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.


买卖股票问题总结

 《代码随想录》总结


代码随想录算法训练营第四十二天| 188.买卖股票的最佳时机IV、309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费_数组