股票问题分析

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

        /**
           动态规划求解
         */

        if(prices == null || prices.length ==0) return 0;

        int n = prices.length ; 
        int[][] dp = new int[n][3];
        /**
        认清以下三个状态:
        dp[i][0]   第i天收盘后手上还持有一只股票时的累计最大收益
        dp[i][1]   第i天收盘后手上没有持有股票但是处于冷冻期时候的最大收益
        dp[i][2]   第i天收盘后手上没有股票且不是冷冻期时候的累计最大收益

        dp[0][0] = -prices[0]  还没卖,收益是负数
        dp[0][1]  dp[0][2]  没有意义 取值为0
         */

         dp[0][0] = -prices[0];

         // 第i天所做的所有操作都是取决于第i-1天的状态
         for(int i =1;i<n;++i){

             // 状态1,第i天手上持有股票,要么是i-1天手上就持有了,要么是i-1天手上没有并且不是冷冻期,那就第i天先买
             dp[i][0] = Math.max(dp[i-1][0],dp[i-1][2]-prices[i]);

             // 状态2,第i天手上没有股票并且属于冷冻期,那么说明只有第i-1 天手上持有了股票,在第i天收盘前卖掉了,才能是冷冻期
             dp[i][1] = dp[i-1][0] +prices[i];

             // 状态3:没有股票且不是冷冻期,要么第i-1 天是冷冻期,要么不是冷冻期且没有持有股票
             dp[i][2] = Math.max(dp[i-1][1],dp[i-1][2]);

         }

         return Math.max(dp[n-1][1],dp[n-1][2]); // 不考虑手上还有股票的情况,因为落袋才有收益
    

 // 方法2  因为第i天只是与第i-1 天有关,所以不存取之前的状态
         int n = prices.length;
         int dp0 = -prices[0];
         int dp1 = 0;
         int dp2 = 0;

        for(int i =1;i<n;++i){
            int nextdp0 = Math.max(dp0,dp2-prices[i]);
            int nextdp1 = dp0 +  prices[i-1];
            int nextdp2 = Math.max(dp1,dp2);
            dp0 = nextdp0;
            dp1= nextdp1;
            dp2 = nextdp2;
        }
        return Math.max(dp1,dp2);

}
}

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

        int n = prices.length;

        // 利用优化后的数组  第i天分为持有和不持有的状态 0表示不持有 1 表示持有
        int[] dp = new int[2];

        dp[0] =0;
        dp[1] = -prices[0];

        for(int i = 1;i<n;++i){
            int tmp = dp[0];

            // 第i天不持有的状态  前一天可能持有也可能不持有
            // 前一天不持有,就不变还是dp0,前一天持有说明当天卖出去了,收回了钱但是要减去手续费
            dp[0] = Math.max(dp[0],dp[1]+prices[i]-fee);

            // 第i天持有, 则可能是前一天持有 dp[1]  前一天不持有 tmp是前一天时候的收益
            dp[1] = Math.max(dp[1],tmp-prices[i]);
        }
        return dp[0];



    }
}

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

        /**
           由于最多完成两笔交易,因此在任意一天结束后,会处于以下五种状态
           1、未进行任何交易
           2、只进行过一次交易
           3、进行了一次买卖
           4、 进行了一次买卖,之后再买入
           5、完成了两次交易
         */

        // 买入价格初始化到最小,   相当于初始化为第0天
         int firstBuy = Integer.MIN_VALUE,first_sell =0;
         int secondBuy = Integer.MIN_VALUE,second_Sell = 0;

        for(int curPrice:prices){
            // 注意买入是负数,卖出是正数
            if(firstBuy < -curPrice){
                firstBuy = -curPrice;  // 买之后的收益为负数
            }

            if(first_sell < firstBuy+curPrice){ // 每利润的情况,当天卖出后收益变多
                 first_sell = firstBuy+curPrice;

            }

            if(secondBuy <first_sell-curPrice){ // 第二次买入
                secondBuy = first_sell-curPrice;
            }

            if(second_Sell  <secondBuy+curPrice){  // 第二次卖出
                second_Sell = secondBuy+curPrice;
            }

        }
        return second_Sell;
    }
}

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

        // 同样当天的情况只是与前一天有关
        if(prices.length ==0) return 0;
        int n = prices.length;
        
        // 分成两种情况,如果k大于n/2 ,就当成普通的情况来处理
        if(k>= n/2){ //说明说有的都可以进行买卖
            int maxProfix =0;
            for(int i =1;i<n;++i){
                if(prices[i] > prices[i-1]){ // 只要有收益就进行买卖
                    maxProfix += prices[i] - prices[i-1];
                }
            }
            return maxProfix;
        }

        // 小于原本内的时候就进行动态规划
        int[][] dp = new int[k+1][n]; // k表示第几次交易,n表示第几天

        for(int i =1;i<=k;++i){
            // 当前手上持有股票,初始情况下第一次交易,想持有,只能以第0天的价格买入
            int localMax = dp[i-1][0] - prices[0];

            for(int j=1;j<n;++j){
                // i 表示第几次交易,j表示第几天
                /**
                      第i比交易后,手上没有股票了,要么是第j-1天手上就已经完成了i比交易不持有了 dp[i][j-1];
                      要么是i-1 次交易时手上还有股票,第j天卖出去了localMax+prices[j]
                 */
                dp[i][j] = Math.max(dp[i][j-1],localMax+prices[j]);

                /**
                   第i比交易后,手上还持有一只股票,要么是i-1 次交易后,手上已经持有了,要么是i-1次交易后手上没持有,
                   第i次以价 格price[j] 买入
                 */

                localMax = Math.max(localMax,dp[i-1][j] -prices[j]);
            }
        }
        return dp[k][n-1];
       

    }
}

+

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zero _s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值