【LeetCode】6个股票问题

总的状态转移方程:

在这里插入图片描述

121. 买卖股票的最佳时机(交易一次)

  • 只能有一次买入,一次买出。求出最大的利润是多少。
    在这里插入图片描述
  • 我起初的思路是,用动态规划的方式。F(i)表示含第i天能获取的最大收益。
    F(i) = max { F(i-1) , 第i天的股票价格 - 第i天以前的最低股票价格 }
class Solution {
    public int maxProfit(int[] prices) {
        //动态规划解题,设每个序号的股价为p(i)
        //设第包括序号i之前的最大收益为F(i),min表示i序号之前的最小值
        //F(i) = max{F(i-1), p(i)-min}
        if(prices.length < 2){
            return 0;
        }
        int min = Math.min(prices[0], prices[1]);
        int f = prices[1] - prices[0];
        for(int i = 2; i<prices.length; i++){
            min = prices[i] < min ? prices[i] : min;
            f = Math.max(f, prices[i] - min);
        }
        return f > 0 ? f : 0;
    }
}
  • 套用总的状态转移方程:
public class Solution {
    public int maxProfit(int[] prices) {
        int dp0 = 0;
        int dp1 = Integer.MIN_VALUE;
        for (int i = 0; i < prices.length; i++) {
            // 手中没有股票 可能昨天就没有;昨天有,今天抛售了。
            dp0 = Math.max(dp0, dp1 + prices[i]);
            // 手中有股票 可能昨天没有,今天刚买的(因为只让买一次,所以新买的话,dp为负的股票价格);昨天就有
            dp1 = Math.max(dp1,  - prices[i]);
        }
        return Math.max(dp0, dp1);
    }
}

122. 买卖股票的最佳时机 II(交易无穷次)

直接套用普适性的状态转移方程:发现和第一道题目只有一点点不同。

public class Demo02 {
    public int maxProfit(int[] prices) {
        int dp0 = 0;
        int dp1 = Integer.MIN_VALUE;
        for (int i = 0; i < prices.length; i++) {
            int tmp = dp0;
            // 手中没有股票 可能昨天就没有;昨天有,今天抛售了。
            dp0 = Math.max(dp0, dp1 + prices[i]);
            // 手中有股票 可能昨天没有,今天刚买的(因为只让买一次,所以新买的话,dp为负的股票价格);昨天就有
            dp1 = Math.max(dp1, tmp - prices[i]);
        }
        return Math.max(dp0, dp1);
    }
}

123. 买卖股票的最佳时机 III(交易两次)

public class Solution {
    public int maxProfit(int[] prices) {
        int dp_2_0 = 0;// 第二次交易,手中没有股票
        int dp_2_1 = Integer.MIN_VALUE;// 第二次交易,手中有股票
        int dp_1_0 = 0;// 第一次交易,手中没有股票
        int dp_1_1 = Integer.MIN_VALUE;// 第一次交易,手中有股票
        for (int price : prices) {
            // 没有股票,可能昨天就没有,或者今天卖了
            dp_2_0 = Math.max(dp_2_0, dp_2_1 + price);
            dp_1_0 = Math.max(dp_1_0, dp_1_1 + price);
            // 持有股票。可能昨天就持有。或者今天新买的
            dp_2_1 = Math.max(dp_2_1, dp_1_0 - price);
            dp_1_1 = Math.max(dp_1_1, -price);
        }
        return dp_2_0;
    }
}

188. 买卖股票的最佳时机 IV(k次交易)

需要对k进行一下判断,否则会超出内存限制。

public class Solution {
    public int maxProfit(int k, int[] prices) {
        // 这种情况下,相当于交易次数为无穷次的情况。
        if (k > prices.length / 2) {
            int dp0 = 0;
            int dp1 = Integer.MIN_VALUE;
            for (int i = 0; i < prices.length; i++) {
                int tmp = dp0;
                // 手中没有股票 可能昨天就没有;昨天有,今天抛售了。
                dp0 = Math.max(dp0, dp1 + prices[i]);
                // 手中有股票 可能昨天没有,今天刚买的(因为只让买一次,所以新买的话,dp为负的股票价格);昨天就有
                dp1 = Math.max(dp1, tmp - prices[i]);
            }
            return Math.max(dp0, dp1);
        }
        // k<= len/2
        int[] dp_k_1 = new int[k + 1]; // k次交易,手中有股票
        int[] dp_k_0 = new int[k + 1]; // k次交易,手中没有股票
        Arrays.fill(dp_k_1, Integer.MIN_VALUE);
        for (int price : prices) {
            for (int i = 1; i <= k; i++) {
                // 第i次交易,手上没有股票,
                dp_k_0[i] = Math.max(dp_k_0[i], dp_k_1[i] + price);
                dp_k_1[i] = Math.max(dp_k_1[i], dp_k_0[i - 1] - price);
            }
        }
        Arrays.sort(dp_k_0);
        return dp_k_0[k];
    }
}

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

在这里插入图片描述

  • 可以发现,和没有冷冻期相比。就是当买入股票的时候,需要是在前两天没买股票的基础上进行。
public class Solution {
    public int maxProfit(int[] prices) {
        // 含有冷冻期,可以交易无数次。
        // 1. 手中可以有股票,可以没股票
        // 2. 天数变量
        int dp_0 = 0;
        int dp_1 = Integer.MIN_VALUE;
        int tmp = 0;// 代表dp_0 i-2那天的。
        for (int i = 0; i < prices.length; i++) {
            int x = dp_0;// 昨天的。
            dp_0 = Math.max(dp_0, dp_1 + prices[i]);
            dp_1 = Math.max(dp_1, tmp - prices[i]);
            tmp = x;// 明天来看的话,tmp就是i-2天的。

        }
        return dp_0;
    }
}

714. 买卖股票的最佳时机含手续费

public class Solution {
    public int maxProfit(int[] prices, int fee) {
        // 有手续费用。我们假定买入的时候需要支付手续费。
        int dp_0 = 0;
        int dp_1 = Integer.MIN_VALUE;
        for (int price : prices) {
            dp_0 = Math.max(dp_0, dp_1 + price);
            dp_1 = Math.max(dp_1, dp_0 - price - fee);
        }
        return dp_0;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章