股票交易变变变!

在面试和金融相关的公司的时候,非常有可能遇到这类题目。这类题也算是动规的常见题目了。

股票无限次交易

在这里插入图片描述

可以进行无限次的交易

思路一:投机取巧法

因为已经事先知道了每一天的股票价格,所以后一天比前一天价格高,就前一天买入,后一天卖出。
如果价格后一天比前一天价格低或者是一样的,我就不买入也不卖出

public int maxProfit (int[] prices) {
        // write code here
        
        int profit = 0;
        for(int i= 1;i < prices.length;i++){
            if(prices[i] > prices[i-1]){
                profit += prices[i]-prices[i-1];
            }
        }
        return profit;
    }

思路二:动态规划

设置动态规划的方程是
dp[i] [2] i表示的是第i天,2表示的是两种状态 0 表示第i天不持有股票,1表示第i天持有股票 可以获得的最大收益

public int maxProfit2 (int[] prices) {
        // write code here
        if(prices.length == 0) return 0;
        int[][] dp = new int[prices.length][2];

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

        for (int i = 1; i< prices.length;i++){

            //第i天未持有股票,两个可能:
            //1.在前面i-1天都持有,第i天卖掉了,卖掉价值增加。dp[1][i - 1] + prices[i - 1]
            //2.到当前为止都为未持有,维持第i-1天的结果。dp[0][i - 1]
            dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]+prices[i]);


            //第i天持有股票,两个可能:
            //1.在前面i-1天都未持有,第i天买入了,总价值减少。dp[0][i - 1] - prices[i - 1]
            //2.到当前为止都为持有,维持第i-1天的结果。dp[1][i - 1]
            dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
        }

        //返回最后一天不持有股票的可以获得的最大价值
        return dp[prices.length-1][0];

    }

股票的最大交易(二)

在这里插入图片描述

和第一个不同的就是对于交易的次数有了限制。
思路:动态规划

还是使用动态规划,两个维度,第一个维度表示天数,第二个维度表示交易,但是第二个维度有5中状态。
dp[i] [0] 表示从开始第i天不持有股票
dp[i] [1] 表示第i天持有股票,且是第一次持有。
dp[i] [2] 表示第i天不持有股票,且是第一次不持有。
dp[i] [3] 表示第i天持有股票,且是第二次持有。
dp[i] [4] 表示第i天不持有股票,且是第二次不持有。

在这里插入图片描述

 public int maxProfitII (int[] prices) {
        if(prices.length == 0) return 0;
        int[][] dp=new int[prices.length][5];
        dp[0][1]=-prices[0];
        dp[0][3]=-prices[0];
        for (int i=1;i<prices.length;i++){
            dp[i][0]=dp[i-1][0];
            //之前就持有 和 第i天买入
            dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
            //之前就卖出了 和 当天卖出
            dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);
            //之前就已经进行第二次交易了  和 第i天进行第二次交易买入
            dp[i][3]=Math.max(dp[i-1][3],dp[i-1][2]-prices[i]);
            //之前就已经进行第二次交易了  和 第i天进行第二次交易卖出
            dp[i][4]=Math.max(dp[i-1][4],dp[i-1][3]+prices[i]);
        }
        
        //关于这里为什么可以直接返回的是交易两次不持有股票的状态
        //而不是在一次都没有交易、交易一次和交易两次后不持有股票中选择最大的收益
        //暂时还不太明白
        return dp[prices.length-1][4];
    }

买卖股票的最好时机

在这里插入图片描述

这道题也是很经典的一道题,在leetcode 121 中也有原题。

思路:动态规划
dp[i] [0] 表示第i天不持有股票
dp[i] [1] 表示第i天持有股票

 public int maxProfit (int[] prices) {
        // write code here
         if(prices.length == 0) return 0;
        int[][] dp=new int[prices.length][2];

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

        for(int i =1;i<prices.length;i++){
            //当天不持有股票 可能是前一天不持有 或者是当天卖掉了
            dp[i][0] = Math.max(dp[i-1][0] , dp[i-1][1]+prices[i]);
            
            //当天持有股票可能是 前一天持有 或者是当天是第一次买入
            //一定只有0-prices[i] 才能体现出是只可以交易一次
            //如果写dp[i-1][0] 就无法确定交易了几次
            //因为上一个 dp[i-1][0]  不持有股票的状态可能是已经交易过的
            dp[i][1] = Math.max(dp[i-1][1],0-prices[i]);
        }
        
        return dp[prices.length-1][0];
    }
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值