算法day35-动态规划(8)

目录

  1.  买卖股票的最佳时机
  2. 买卖股票的最佳时机II
  3. 买卖股票的最佳时机III

一、买卖股票的最佳时机

 https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/?envType=problem-list-v2&envId=8At1GmaZ

  1. 状态定义

    • 使用一个二维数组 dp[i][0] 表示在第 i 天持有股票时的最大收益。

    • 使用 dp[i][1] 表示在第 i 天不持有股票时的最大收益。

  2. 初始条件

    • 在第 0 天,如果持有股票,最大收益是 -prices[0](即买入股票的花费)。

    • 在第 0 天,如果不持有股票,最大收益是 0(即没有操作)。

  3. 状态转移

    • 对于每一天 i(从 1 到 length - 1),有两种选择:

      • 持有股票:可以选择继续持有前一天的股票,或者在今天再次买入股票(此时的收益为 -prices[i]),即 dp[i][0] = Math.max(dp[i-1][0], -prices[i])

      • 不持有股票:可以选择继续不持有前一天的股票,或者在今天卖出股票(此时的收益为 dp[i-1][0] + prices[i]),即 dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] + prices[i])

  4. 最终结果

    • 在最后一天(第 length-1 天),我们关心的是不持有股票的最大收益,即 dp[length-1][1]

时间复杂度:

该算法的时间复杂度为 O(n),其中 n 为股票价格数组的长度,因为只需要遍历一次数组。

空间复杂度:

该算法的空间复杂度为 O(n),主要是由 dp 数组占用的空间决定。

class Solution {
    public int maxProfit(int[] prices) {
        //dp[i][0]持有股票得到的最大收益,dp[i][1]不持股最大收益
        if(prices == null || prices.length == 0)    return 0;
        int length = prices.length;
        int[][] dp = new int[length][2];
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i=1; i<length; i++){
            dp[i][0] = Math.max(dp[i-1][0], -prices[i]);
            dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] + prices[i]);
        }
        return dp[length-1][1];
    }
}

二、买卖股票的最佳时机II——买卖多次

https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/

   与上一题的不同是:可以在同一天买入和卖出,且可以买卖多次。

class Solution {
    public int maxProfit(int[] prices) {
        // int sum = 0;
        // for(int i=0; i<prices.length-1; i++){
        //     if(prices[i+1] > prices[i]){        //如果后一天大于当天,则卖-买
        //         sum += prices[i+1]-prices[i];
        //     }
        // }
        // return sum;

        if(prices == null || prices.length == 0)    return 0;
        int length = prices.length;
        int[][] dp = new int[length][2];
        //在第0天持有股票的最大收益
        dp[0][0] = -prices[0];
        //在第0天不持股的最大收益
        dp[0][1] = 0;
        for(int i=1; i<length; i++){
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]-prices[i]);      //dp[i-1][1]是前几天累积的收益
            dp[i][1] = Math.max(dp[i-1][1], dp[i][0]+prices[i]);
        }
        return dp[length-1][1];
    }
}

 

三、买卖股票的最佳时机III

 https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/?envType=problem-list-v2&envId=8At1GmaZ

   与前面两题的区别是:股票至多买卖两次。

class Solution {
    public int maxProfit(int[] prices) {
        int length = prices.length;
        int[][] dp = new int[length][5];
        //第0天持有股票的最大收益
        dp[0][0] = 0;      
        dp[0][1] = -prices[0];     //第一次持有
        dp[0][2] = 0;  //第一次不持有
        dp[0][3] = -prices[0];  //第二次持有
        dp[0][4] = 0;   //第二次不持有

        for(int i=1; i<length; i++){
            dp[i][0] = dp[i-1][0];
            dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i]);
            dp[i][2] = Math.max(dp[i-1][2], dp[i-1][1] + prices[i]);
            dp[i][3] = Math.max(dp[i-1][3], dp[i-1][2] - prices[i]);
            dp[i][4] = Math.max(dp[i-1][4], dp[i-1][3] + prices[i]);
        }
        return Math.max(dp[length-1][2],dp[length-1][4]);
    }
}

 

class Solution {
    public int maxProfit(int[] prices) {
        // int sum = 0;
        // for(int i=0; i<prices.length-1; i++){
        //     if(prices[i+1] > prices[i]){        //如果后一天大于当天,则卖-买
        //         sum += prices[i+1]-prices[i];
        //     }
        // }
        // return sum;

        if(prices == null || prices.length == 0)    return 0;
        int length = prices.length;
        int[][] dp = new int[length][2];
        //在第0天持有股票的最大收益
        dp[0][0] = -prices[0];
        //在第0天不持股的最大收益
        dp[0][1] = 0;
        for(int i=1; i<length; i++){
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]-prices[i]);      //dp[i-1][1]是前几天累积的收益
            dp[i][1] = Math.max(dp[i-1][1], dp[i][0]+prices[i]);
        }
        return dp[length-1][1];
    }
}
posted @ 2025-06-06 23:53  筱倩  阅读(34)  评论(0)    收藏  举报