• 第50天Dynamic Programming Stock 123、188


    123. Best Time to Buy and Sell Stock III

    • 关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。
    • 公式:
      • dp[i][0]在for loop里不需要更新,或者更新了也是dp[i-1][0] 因为没有操作
      • dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])
        • 操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
        • 操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2] 这里这个状态,一层层倒推回去会到初始化的dp[0][2] = 0,所以这里包含了买卖一次,或者不买卖的最优情况。
      • 同理dp[i][4] = max(dp[i - 1][3] + prices[i], dp[i - 1][4]),这里包含了买卖两次,买卖一次,或者不买卖的最优情况。
    • 这也是为什么最后只需要return dp[prices.length-1][4];
    • 初始化:
      • dp[0][2] = 0; 第0天做第一次卖出的操作,这个初始值应该是多少呢?首先卖出的操作一定是收获利润,整个股票买卖最差情况也就是没有盈利即全程无操作现金为0,从递推公式中可以看出每次是取最大值,那么既然是收获利润如果比0还小了就没有必要收获这个利润了。
      • dp[0][3] = -prices[0]; 第一次还没买入呢,怎么初始化第二次买入呢?第二次买入依赖于第一次卖出的状态,其实相当于第0天第一次买入了,第一次卖出了,然后在买入一次(第二次买入),那么现在手头上没有现金,只要买入,现金就做相应的减少。
    • Time Complexity: O(n)
    • Space Complexity: O(5*n) -> 可以优化成O(1)
    1. // O(n)
    2. class Solution {
    3. public int maxProfit(int[] prices) {
    4. int[][] dp = new int[prices.length][5];
    5. dp[0][0] = 0; // don't have stock
    6. dp[0][1] = -prices[0]; // have stock first time
    7. dp[0][2] = 0; // sell stock first time
    8. dp[0][3] = -prices[0]; // have stock second time
    9. dp[0][4] = 0; // sell stock second time
    10. for (int i=1; i
    11. // dp[i][0] = dp[i-1][0];
    12. dp[i][1] = Math.max(-prices[i], dp[i-1][1]);
    13. dp[i][2] = Math.max(dp[i-1][1]+prices[i], dp[i-1][2]);
    14. dp[i][3] = Math.max(dp[i-1][2]-prices[i], dp[i-1][3]);
    15. dp[i][4] = Math.max(dp[i-1][3]+prices[i], dp[i-1][4]);
    16. }
    17. return dp[prices.length-1][4];
    18. }
    19. }
    20. // O(1)
    21. class Solution {
    22. public int maxProfit(int[] prices) {
    23. int[] dp = new int[5];
    24. dp[0] = 0; // don't have stock
    25. dp[1] = -prices[0]; // have stock first time
    26. dp[2] = 0; // sell stock first time
    27. dp[3] = -prices[0]; // have stock second time
    28. dp[4] = 0; // sell stock second time
    29. for (int i=1; i
    30. int temp = dp[1];
    31. dp[1] = Math.max(-prices[i], dp[1]);
    32. int temp2 = dp[2];
    33. dp[2] = Math.max(temp+prices[i], dp[2]);
    34. int temp3 = dp[3];
    35. dp[3] = Math.max(temp2-prices[i], dp[3]);
    36. dp[4] = Math.max(temp3+prices[i], dp[4]);
    37. }
    38. return dp[4];
    39. }
    40. }
    • Space Complexity优化甚至可以写成更干净的版本【不需要】
      • dp[2]利用的是当天的dp[1](第一次买入的状态) dp[1] = max(dp[1], dp[0] - prices[i]);
      • 1. 如果dp[1]取dp[1],即保持买入股票的状态,那么 dp[2] = max(dp[2], dp[1] + prices[i]);中dp[1] + prices[i] 就是今天卖出。
      • 2. 如果dp[1]取dp[0] - prices[i],今天买入股票,那么dp[2] = max(dp[2], dp[1] + prices[i]);中的dp[1] + prices[i]相当于是在再卖出股票,一买一卖收益为0,对所得现金没有影响。相当于今天买入股票又卖出股票,等于没有操作,保持昨天卖出股票的状态了
    1. class Solution {
    2. public int maxProfit(int[] prices) {
    3. int[] dp = new int[5];
    4. dp[0] = 0; // don't have stock
    5. dp[1] = -prices[0]; // have stock first time
    6. dp[2] = 0; // sell stock first time
    7. dp[3] = -prices[0]; // have stock second time
    8. dp[4] = 0; // sell stock second time
    9. for (int i=1; i
    10. dp[1] = Math.max(-prices[i], dp[1]);
    11. dp[2] = Math.max(dp[1]+prices[i], dp[2]);
    12. dp[3] = Math.max(dp[2]-prices[i], dp[3]);
    13. dp[4] = Math.max(dp[3]+prices[i], dp[4]);
    14. }
    15. return dp[4];
    16. }
    17. }

  • 相关阅读:
    Excel VLOOKUP实用教程之 04 vlookup如何实现三变量查找,三个条件字段查询数据?(教程含数据excel)
    申报高企的条件你真的满足了吗?
    Rust常见集合
    java spring cloud 企业电子招标采购系统源码:营造全面规范安全的电子招投标环境,促进招投标市场健康可持续发展
    软件部2022届讲课底稿------多重背包问题
    虹科分享 | 网络保险:有效承保网络风险解决方案
    Pytorch之RepVGG图像分类
    Spring中有哪些情况会导致@Bean注入失效呢?
    [算法]数组给定长度的所有排列
    MATLAB - 用命令行设计 MPC 控制器
  • 原文地址:https://blog.csdn.net/Kathrynzzz/article/details/127761963