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


     题目与题解

    参考资料买卖股票总结

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

    题目链接:309.最佳买卖股票时机含冷冻期

    代码随想录题解:309.最佳买卖股票时机含冷冻期

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

    解题思路:

            听说状态比较多,直接放弃看答案,状态转移有点复杂的。

    看完代码随想录之后的想法 

            关键是要理解在有冷冻状态的条件下,股票可能有哪些状态,它们之间的关系是什么,才能直到状态变化的依赖关系,得出状态转移公式。

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

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

            

    那么转移到状态一有三种情况:保持买入状态不变,不买不卖(状态1->1);刚结束冷冻状态,直接买入(状态4->1);处于卖出一段时间的状态,再买入(状态2->1)

    转移到状态2有两种情况:前面没有冷冻,保持卖出状态不变,不买不卖(状态2->2);刚结束冷冻状态,但不买入,保持卖出状态(状态4->2)

    转移到状态3只有一种情况:处于买入状态,然后卖出(状态1->3)

    转移到状态4只有一种情况:刚卖出(状态3->4)

    递推公式根据状态转移就可以清楚的得到了。初始化状态1为-prices[0],其余状态由于还未产生交易,初始化为0。

    最后返回时,要从状态2,3,4中选一个最大值。因为今天卖出,冷冻,和保持卖出状态这三种都属于卖出的状态,有可能都有最大值。

    1. class Solution {
    2. public int maxProfit(int[] prices) {
    3. if (prices.length <= 1) return 0;
    4. int[][] dp = new int[prices.length][4];
    5. dp[0][0] = -prices[0];
    6. for (int i = 1; i < prices.length; i++) {
    7. dp[i][0] = Math.max(dp[i-1][0], Math.max(dp[i-1][1]-prices[i], dp[i-1][3]-prices[i]));
    8. dp[i][1] = Math.max(dp[i-1][1], dp[i-1][3]);
    9. dp[i][2] = dp[i-1][0] + prices[i];
    10. dp[i][3] = dp[i-1][2];
    11. }
    12. return Math.max(dp[prices.length-1][1], Math.max(dp[prices.length-1][2], dp[prices.length-1][3]));
    13. }
    14. }

    遇到的困难

            第一次遇到这么复杂的状态,记下了

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

    题目链接:714.买卖股票的最佳时机含手续费

    代码随想录题解:714.买卖股票的最佳时机含手续费

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

    解题思路:

            这题跟买卖股票II几乎一样,就是在卖出状态时,如果卖出了股票,需要增加一个手续费,即dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] + prices[i] - fee)。最后仍旧返回dp[prices.length-1][1]即可。

    1. class Solution {
    2. public int maxProfit(int[] prices, int fee) {
    3. if (prices.length <= 1) return 0;
    4. int[][] dp = new int[prices.length][2];
    5. dp[0][0] = -prices[0];
    6. dp[0][1] = 0;
    7. for (int i = 1; i < prices.length; i++) {
    8. dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] - prices[i]);
    9. dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] + prices[i] - fee);
    10. }
    11. return dp[prices.length-1][1];
    12. }
    13. }

    看完代码随想录之后的想法 

            无

    遇到的困难

            写dp[i][0]递推公式的时候一开始思路不清晰写成了dp[i-1][0] - prices[i],这肯定不对,要牢记卖出后才能买入,必然用dp[i-1][1] - prices[i]来递推。

    今日收获

           学习了一下复杂状态的买卖股票方法, 复习总结了买卖股票系列问题。

            买卖股票问题的核心解法是定义dp为手中持有的现金,再根据买入卖出加减持有值。

            买卖一次和买卖多次的状态转移方法有点类似,最后可以用公式总结出来;如果出现类似冷冻期,手续费之类的特殊值,需要判断其状态转移是否有变化,递推公式是否需要修改,基本公式就是买卖股票IV里的规律总结了。

  • 相关阅读:
    海康威视相机在QTcreate上的使用教程
    C++静态代码检查工具 - cppcheck
    防火墙、firewalld指令、更改yum源为阿里云的yum源及常见问题
    有能帮我看看这个怎么恢复吗?
    239. 滑动窗口最大值
    为什么个人IP对任何行业都至关重要
    mapreduce中的ReduceTask工作机制(Hadoop)
    Sentry Relay 二次开发调试简介
    E. Block Sequence Codeforces Round 903 (Div. 3)
    组合数(2)获取C(n,k)组合数列表的QT实现
  • 原文地址:https://blog.csdn.net/qq_42973684/article/details/138203489