• 代码随想录算法训练营第五十一天 |309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费、总结


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

    题目链接/文章讲解:代码随想录

    视频讲解:动态规划来决定最佳时机,这次有冷冻期!| LeetCode:309.买卖股票的最佳时机含冷冻期_哔哩哔哩_bilibili

     思考:

    1.确定dp数组(dp table)以及下标的含义

    dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]

    具体可以区分出如下四个状态:

    • 状态一:持有股票状态(今天买入股票,或者是之前就买入了股票然后没有操作,一直持有)
    • 不持有股票状态,这里就有两种卖出股票状态
      • 状态二:保持卖出股票的状态(两天前就卖出了股票,度过一天冷冻期。或者是前一天就是卖出股票状态,一直没操作)
      • 状态三:今天卖出股票
    • 状态四:今天为冷冻期状态,但冷冻期状态不可持续,只有一天!

    本题为什么要单独列出「今天卖出股票」 一个状态呢?

    因为本题我们有冷冻期,而冷冻期的前一天,只能是 「今天卖出股票」状态,如果是 「不持有股票状态」那么就很模糊,因为不一定是 卖出股票的操作。

    2.确定递推公式

    状态一

    达到买入股票状态即:dp[i][0],有两个具体操作:

    • 操作一:前一天就是持有股票状态(状态一),dp[i][0] = dp[i - 1][0]
    • 操作二:今天买入了,有两种情况
      • 前一天是冷冻期(状态四),dp[i - 1][3] - prices[i]
      • 前一天是保持卖出股票的状态(状态二),dp[i - 1][1] - prices[i]

    那么dp[i][0] = max(dp[i - 1][0], dp[i - 1][3] - prices[i], 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];

    综合如下:

    1. dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);
    2. dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
    3. dp[i][2] = dp[i - 1][0] + prices[i];
    4. dp[i][3] = dp[i - 1][2];

    3.dp数组的初始化

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

    4.确定遍历顺序

    从前向后

    5.举例推导dp数组

    代码实现: 

    1. class Solution {
    2. public:
    3. int maxProfit(vector<int>& prices) {
    4. int n = prices.size();
    5. if (n == 0) return 0;
    6. vectorint>> dp(n, vector<int>(4, 0));
    7. dp[0][0] -= prices[0]; // 持股票
    8. for (int i = 1; i < n; i++) {
    9. dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3] - prices[i], dp[i - 1][1] - prices[i]));
    10. dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
    11. dp[i][2] = dp[i - 1][0] + prices[i];
    12. dp[i][3] = dp[i - 1][2];
    13. }
    14. return max(dp[n - 1][3], max(dp[n - 1][1], dp[n - 1][2]));
    15. }
    16. };
    • 时间复杂度:O(n)
    • 空间复杂度:O(n)

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

    题目链接/文章讲解:代码随想录

    视频讲解:动态规划来决定最佳时机,这次含手续费!| LeetCode:714.买卖股票的最佳时机含手续费_哔哩哔哩_bilibili

    思考:

    相对于动态规划:122.买卖股票的最佳时机II,本题只需要在计算卖出操作的时候减去手续费就可以了,代码几乎是一样的。

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

    代码实现: 

    1. class Solution {
    2. public:
    3. int maxProfit(vector<int>& prices, int fee) {
    4. int n = prices.size();
    5. vectorint>> dp(n, vector<int>(2, 0));
    6. dp[0][0] -= prices[0]; // 持股票
    7. for (int i = 1; i < n; i++) {
    8. dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
    9. dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);
    10. }
    11. return max(dp[n - 1][0], dp[n - 1][1]);
    12. }
    13. };
    • 时间复杂度:O(n)
    • 空间复杂度:O(n)

    三、总结

    题目链接/文章讲解:代码随想录

  • 相关阅读:
    【C++】vector的认识+模拟实现
    通过提示大语言模型进行个性化推荐LLM-Rec: Personalized Recommendation via Prompting Large Language Models
    【常见算法】第三篇:回溯算法
    【python笔记】小甲鱼
    Python tkinter: 开发一个目标检测GUI小程序
    python容器之字典
    C语言——数据在内存中的存储_学习笔记
    【算法练习Day12】树的递归遍历&&非递归遍历
    GitLab忘记管理员密码处理和禁用注册功能
    阿里P8专家爆出:入职阿里必备的598道java面试题,内含算法
  • 原文地址:https://blog.csdn.net/weixin_60353640/article/details/133488268