【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;
    }
}

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