股票问题总结

框架

思路:
明确dp数组的定义,dp[i][k][0]代表 第i天,至多交易K次,并且手上还有股票的最大利润
明确选择:每天都有三种「选择」:买入、卖出、无操作,我们用 buy, sell, rest 表示这三种选择

base case:
dp[-1][k][0] = dp[i][0][0] = 0
dp[-1][k][1] = dp[i][0][1] = -infinity

状态转移方程:
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])

一次交易最大利润

class Solution {
    public int maxProfit(int[] prices) {
        //base case初始状态 dp[-1][0]=0,dp[-1][1]=-99999
        int dp_i_0=0,dp_i_1=Integer.MIN_VALUE;
        //设置一个变量保存前一个状态,使时间复杂度O(1)
        int n=prices.length;
        for(int i=0;i<n;i++){
            //今天没有持股的情况
            dp_i_0=Math.max(dp_i_0,dp_i_1+prices[i]);
            //今天持股的情况
            dp_i_1=Math.max(dp_i_1,-prices[i]);
        }
        return dp_i_0;

    }
}

尽可能多的交易

class Solution {
    public int maxProfit(int[] prices) {

        int n=prices.length;
        int dp_i_0=0,dp_i_1=Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            int tmp=dp_i_0;
            dp_i_0=Math.max(dp_i_0,dp_i_1+prices[i]);
            dp_i_1=Math.max(dp_i_1,tmp-prices[i]);
        }
        return dp_i_0;
        
    }
}

最多俩次交易

法1

class Solution {
    public int maxProfit(int[] prices) {
       
    int dp_i10 = 0, dp_i11 = Integer.MIN_VALUE;
    int dp_i20 = 0, dp_i21 = Integer.MIN_VALUE;
    for (int price : prices) {
        dp_i20 = Math.max(dp_i20, dp_i21 + price);
        dp_i21 = Math.max(dp_i21, dp_i10 - price);
        dp_i10 = Math.max(dp_i10, dp_i11 + price);
        dp_i11 = Math.max(dp_i11, -price);
    }
    return dp_i20;
    }
}

法2

class Solution {
    public int maxProfit(int[] prices) {
        //dp[-1][k][0] = 0
        //dp[-1][k][1] = -infinity
        //dp[i][0][0] = 0
        //dp[i][0][1] = -infinity
    
    int max_k = 2;
    int n=prices.length;
    int[][][] dp = new int[n][max_k + 1][2];
    if(n==0) return 0;
    for (int i = 0; i < n; i++) {
        for (int k = max_k; k >= 1; k--) {
            if (i - 1 == -1) { 
                /*处理 base case */ 
                dp[0][k][0]=0;
                dp[0][k][1]=-prices[0];
                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]);
        }
    }
    // 穷举了 n × max_k × 2 个状态,正确。
    return dp[n - 1][max_k][0];

    }
}

多次交易含冷冻期

class Solution {
    public int maxProfit(int[] prices) {

        int n=prices.length;
        int dp_i_0=0,dp_i_1=Integer.MIN_VALUE;
        int dp_i_pre=0;//dp[i-2][0]

        for(int i=0;i<n;i++){
            int tmp=dp_i_0;
            dp_i_0=Math.max(dp_i_0,dp_i_1+prices[i]);
            dp_i_1=Math.max(dp_i_1,dp_i_pre-prices[i]);
            dp_i_pre=tmp;
        }
        return dp_i_0;

    }
}

多次交易含手续费

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int n=prices.length;
        int dp_i_0=0,dp_i_1=Integer.MIN_VALUE;
        
        for(int i=0;i<n;i++){
            int tmp=dp_i_0;
            dp_i_0=Math.max(dp_i_0,dp_i_1+prices[i]);
            dp_i_1=Math.max(dp_i_1,tmp-prices[i]-fee);
        }
        return dp_i_0;

    }
}
posted @ 2020-05-10 20:49  程序员小宇  阅读(152)  评论(0)    收藏  举报