Day34 | 121买卖股票的最佳时机&122买卖股票的最佳时机 II&123买卖股票的最佳时机 III&188买卖股票的最佳时机 IV&309&714

172 阅读3分钟

买卖股票的最佳时机 LeetCode 121

题目链接:[LeetCode 121 - 简单]

思路

该题只能有一次买进和卖出的机会。 因此可以直接将dp数组转化为一个变量。

动态规划:

class Solution {
    public int maxProfit(int[] prices) {
        int[] dp = new int[prices.length];
        int min = prices[0];
        for(int i=1;i<prices.length;i++){
            if(prices[i]>min){
                dp[i]=Math.max(prices[i]-min,dp[i-1]);
            }else{
                dp[i]=dp[i-1];
            }
            min=Math.min(prices[i],min);
        }
        return dp[prices.length-1];
    }
}

优化后

class Solution {
    public int maxProfit(int[] prices) {
        int min = Integer.MAX_VALUE;
        int res = 0;
        for(int price:prices){
            res=Math.max(res,price-min);
            min=Math.min(min,price);
        }
        return res;
    }
}

买卖股票的最佳时机 II LeetCode 122

题目链接:[LeetCode 122 - 中等]

思路

发现之前在贪心中做过该题 使用动态规划又是不同的思路

动态规划:

一维数组

class Solution {
    public int maxProfit(int[] prices) {
        int[] dp = new int[prices.length];
        int min = prices[0];
        for(int i=1;i<prices.length;i++){
            if(prices[i]>min){
                dp[i]=dp[i-1]+prices[i]-min;
                min=prices[i];
            }else{
                dp[i]=dp[i-1];
                min=Math.min(min,prices[i]);
            }
        }
        return dp[prices.length-1];
    }
}

一个变量

class Solution {
    public int maxProfit(int[] prices) {
        int res = 0;
        int min = prices[0];
        for(int i=1;i<prices.length;i++){
            if(prices[i]>min){
                res+=prices[i]-min;
                min=prices[i];
            }else{
                min=Math.min(min,prices[i]);
            }
        }
        return res;
    }
}

另一种优化思路

class Solution {
    public int maxProfit(int[] prices) {
        int[] dp = new int[2];
        //0持有 1卖出
        dp[0]=-prices[0];
        dp[1]=0;
        for(int i=1;i<prices.length;i++){
            dp[0]=Math.max(dp[0],dp[1]-prices[i]);
            dp[1]=Math.max(dp[1],dp[0]+prices[i]);
        }
        return dp[1];
    }
}

贪心:

class Solution {
    public int maxProfit(int[] prices) {
        int result = 0;
        for(int i=0;i<prices.length-1;i++){
            if(prices[i]<prices[i+1]){
                result += prices[i+1] - prices[i];
            }
        }
        return result;
    }
}

买卖股票的最佳时机 III LeetCode 123

题目链接:[LeetCode 123 - 困难]

思路

定义了五种状态。

动态规划:

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length==1)return 0;
        int[][] dp = new int[prices.length][5];
        //定义五种状态,0:没有操作 1:第一次买入 2:第一次卖出3:第二次买入4:第二次卖出
        dp[0][1]=-prices[0];
        dp[0][3]=-prices[0];
        for(int i=1;i<prices.length;i++){
            dp[i][1]=Math.max(dp[i-1][1],-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][2]-prices[i]);
            dp[i][4]=Math.max(dp[i-1][4],dp[i][3]+prices[i]);
        }
        return dp[prices.length-1][4];
    }
}
class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length==1)return 0;
        int[] dp = new int[5];
        //定义五种状态,0:没有操作 1:第一次买入 2:第一次卖出3:第二次买入4:第二次卖出
        dp[1]=-prices[0];
        dp[3]=-prices[0];
        for(int i=1;i<prices.length;i++){
            dp[1]=Math.max(dp[1],-prices[i]);
            dp[2]=Math.max(dp[2],dp[1]+prices[i]);
            dp[3]=Math.max(dp[3],dp[2]-prices[i]);
            dp[4]=Math.max(dp[4],dp[3]+prices[i]);
        }
        return dp[4];
    }
}

买卖股票的最佳时机 IV LeetCode 188

题目链接:[LeetCode 188 - 困难]

思路

与#123思路一致,但是代码稍有不同。

动态规划:

class Solution {
    public int maxProfit(int k, int[] prices) {
        int[] dp = new int[k*2+1];
        for(int j=0;j<k;j++){
            dp[j*2+1]=-prices[0];
        }
        for(int i=0;i<prices.length;i++){
            dp[1]=Math.max(dp[1],-prices[i]);
            dp[2]=Math.max(dp[2],dp[1]+prices[i]);
            for(int j=1;j<k;j++){
                dp[2*j+1]=Math.max(dp[2*j+1],dp[2*j]-prices[i]);
                dp[2*j+2]=Math.max(dp[2*j+2],dp[2*j+1]+prices[i]);
            }
        }
        return dp[2*k];
    }
}

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

题目链接:[LeetCode 309 - 中等]

思路

主要为冷静期期间不能购买股票,因此需要在不持有收益时卖出。

动态规划:

class Solution {
    public int maxProfit(int[] prices) {
        int[][] dp = new int[prices.length+1][2];
        //0:第i天持有股票收益    1:第i天不持有股票收益
        dp[1][0]=-prices[0];

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

买卖股票的最佳时机 LeetCode 714

题目链接:[LeetCode 714 - 中等]

思路

动态规划:

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int[] dp = new int[2];
        dp[0]=-prices[0];
        for(int i=1;i<prices.length;i++){
            dp[0]=Math.max(dp[1]-prices[i],dp[0]);
            dp[1]=Math.max(dp[0]+prices[i]-fee,dp[1]);
        }
        return dp[1];
    }
}