动态规划(07)

95 阅读2分钟

Day12 股票问题(02)

1、123. 买卖股票的最佳时机 III

  • 思路:
    • 股票问题解题模板。
      • dp[i][k][0]=MAX[dp[i1][k][0],dp[i1][k][1]+price[i]]dp[i][k][0] = MAX[dp[i-1][k][0],dp[i-1][k][1]+price[i]]
      • dp[i][k][1]=MAX[dp[i1][k][1],dp[i1][k1][0]price[i]]dp[i][k][1] = MAX[dp[i-1][k][1],dp[i-1][k - 1][0]-price[i]]
    • 注意base case
      • k从1开始,最大取2。
      • dp[0][...][0]=0dp[0][...][0] = 0 第0天没有未持有股票,则收益一定为0
      • dp[0][...][1]=price[0]dp[0][...][1] = -price[0] 第0天持有股票,则最大收益一定是-price[0]
    class Solution {
        public int maxProfit(int[] prices) {
            int len = prices.length;
            int[][][] dp = new int[len][3][2];
            for (int i = 0; i < len; i++) {
                for (int k = 1; k < 3; k++) {
                    if (i == 0) {
                        // 处理 base case
                        dp[i][k][0] = 0;
                        dp[i][k][1] = -prices[i];
                        continue;
                    }
                    dp[i][k][0] = Math.max(dp[i - 1][k][0], dp[i - 1][k][1] + prices[i]);
                    dp[i][k][1] = Math.max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - prices[i]);
                }
            }
            return dp[len - 1][2][0];
        }
    }
    
  • 空间复杂度优化(辅助理解base case)
    class Solution {
        public int maxProfit(int[] prices) {
            int len = prices.length;
            //每天一共五种状态 没有买卖 第一次买入 第一次卖出  完成一次买卖买入 完成一次买卖卖出
            //base case buy1第一天买入   buy2 第一天买卖一次为0,再买一次=buy1
            int buy1 = -prices[0], buy2 = -prices[0];
            //sell 第一天买卖利润为0   第一天买卖两次还为0
            int sell1 = 0, sell2 = 0;
            for (int i = 1; i < len; i++) {
                //一次买入今天未操作、 未进行买卖今天第一次买入
                buy1 = Math.max(buy1, -prices[i]);
                //完成一次买卖未操作、 第一次买入后今天卖出
                sell1 = Math.max(sell1, buy1 + prices[i]);
                //完成一次买卖后买入未操作、完成一次买卖后第一次买入
                buy2 = Math.max(buy2, sell1 - prices[i]);
                //完成二次买卖后为操作、完成一次买卖后买入今天卖出
                sell2 = Math.max(sell2, buy2 + prices[i]);
            }
            return sell2;
        }
    }
    

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

  • 股票模板
    class Solution {
        public int maxProfit(int k, int[] prices) {
            int len = prices.length;
            int[][][] dp = new int[len][k + 1][2];
            for (int i = 0; i < len; i++) {
                dp[i][0][0] = 0;
                dp[i][0][1] = Integer.MIN_VALUE;
            }
            for (int i = 0; i < len; i++) {
                //k从1开始
                for (int j = 1; j < k + 1; j++) {
                    if (i == 0) {
                        //第0天买卖k次未持有股票的最大收益为0
                        dp[i][j][0] = 0;
                        //第0天买卖k次持有股票的最大收益为-prices[0]
                        dp[i][j][1] = -prices[i];
                        continue;
                    }
                    dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
                    dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
                }
            }
            return dp[len - 1][k][0];
        }
    }
    
  • 空间复杂度优化
    • 同1解法思路一致,取buy[]和sell[]数组
    class Solution {
        public int maxProfit(int k, int[] prices) {
            int len = prices.length;
            if (len == 0) return 0;
            int[] buy = new int[k];
            int[] sell = new int[k];
            Arrays.fill(buy, -prices[0]);
            for (int i = 1; i < len; i++) {
                buy[0] = Math.max(buy[0], -prices[i]);
                sell[0] = Math.max(sell[0], buy[0] + prices[i]);
                for (int j = 1; j < k; j++) {
                    buy[j] = Math.max(buy[j], sell[j - 1] - prices[i]);
                    sell[j] = Math.max(sell[j], buy[j] + prices[i]);
                }
            }
            return sell[k - 1];
        }
    }