当前位置:   article > 正文

代码随想录训练营day50, 买卖股票的最佳时间III, IV

代码随想录训练营day50, 买卖股票的最佳时间III, IV

买卖股票的最佳时间III

这里的关键就是至多买卖两次, 所以可以买一次, 买两次, 也可以不买卖

  1. dp数组含义. 一天有五个状态

    0 没有操作   1 第一次买入   2 第一次卖出   3 第二次买入   4 第二次卖出

dp[i][j]中, i表示第i天, j表示五种状态,

  1. 确定递推公式, 和之前的股票问题一样, 对于dp[i][1]两种情况:

    第i天买的: dp[i-1][0] - prices[i]

    沿用之前: dp[i - 1][1], 然后取max

    对于dp[i][2]: 第i天卖出: dp[i - 1][1] + prices[i]

    沿用之前: dp[i-1][2]

    然后同理: dp[i][3] = max(dp[i-1][3], dp[i-1][2]-prices[i]) do[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i])

  2. 初始化: 第0天没有操作, 所以是dp[0][0]=0, 第0天买入, 就是dp[0][1]=-prices[0], dp[0][2]=0, 因为没有利润, dp[0][3] = -prices[0], 只要买入现金就减少, dp[0][4]同样为0

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int len = prices.length;
  4. if(len == 0 || prices == null){
  5. return 0;
  6. }
  7. int[][] dp = new int[len + 1][5];
  8. //inni, dp数组一开始就是0, 所以没必要定义下面的0
  9. dp[0][0] = 0;
  10. dp[0][1] = -prices[0];
  11. dp[0][2] = 0;
  12. dp[0][3] = -prices[0];
  13. dp[0][4] = 0;
  14. //开始遍历
  15. for(int i = 1; i < len; i++){
  16. //buy stock1: buy at that day/like before
  17. dp[i][1] = Math.max(dp[i - 1][0] - prices[i], dp[i - 1][1]);
  18. //sell stock1: sell at that day/like before
  19. dp[i][2] = Math.max(dp[i - 1][1] + prices[i], dp[i - 1][2]);
  20. //buy stock2: buy at that day/like before
  21. dp[i][3] = Math.max(dp[i - 1][2] - prices[i], dp[i - 1][3]);
  22. //sell stock2: sell that day/like befor
  23. dp[i][4] = Math.max(dp[i - 1][3] + prices[i], dp[i - 1][4]);
  24. }
  25. return dp[len - 1][4];
  26. }
  27. }

买卖股票的最佳时机IV (最多完成k笔交易)

和之前的III相似, 但是这里有多种条件了, 可以发现偶数就是卖出, 奇数就是买入, 由于题目要求k笔交易, 所以j的范围就是2*k+1

这里的定义是dp[i][1]是买入股票的状态

递推公式: dp[i][1]状态有两种:

第i天买入, dp[i-1][0] - prices[i]

沿用之前, dp[i - 1][1]

同理dp[i][2]也有两种:

第i天卖出, dp[i-1][1] + prices[i]

沿用之前, dp[i - 1][2]

然后类比剩下的……

初始化: 可以发现是偶数是说明为卖出, 都为0; 为奇数时, 都为-pricesi

**细节:

  1. 首先初始化所有的奇数为-prices[0]

  2. 然后两个for循环, 把买入和卖出看成一个整体的操作, +=2

  3. 循环内, +1就是买的情况, +2就是卖的情况

  1. class Solution {
  2. public int maxProfit(int k, int[] prices) {
  3. int len = prices.length;
  4. if(len == 0 || prices == null){
  5. return 0;
  6. }
  7. //由于最多有k次, 所以操作就是2k+1
  8. int[][] dp = new int[len + 1][2*k + 1];
  9. //初始化所有奇数, <2*k是因为从1开始的
  10. for(int j = 1; j < 2*k; j +=2){
  11. dp[0][j] = -prices[0];
  12. }
  13. //开始遍历, 把买入卖出看成单次
  14. for(int i = 1; i < len; i++){
  15. //这里是2k - 1, 因为条件有个j+2
  16. for(int j = 0; j < 2*k -1; j += 2){
  17. //分为奇数和偶数的情况
  18. //j+1表示奇数, 也就是买入
  19. dp[i][j + 1] = Math.max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]);
  20. dp[i][j + 2] = Math.max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]);
  21. }
  22. }
  23. //还记得上道题:卖2次就填4
  24. return dp[len - 1][k*2];
  25. }
  26. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/286720
推荐阅读
相关标签
  

闽ICP备14008679号