• 多种买卖股票算法解决方案


    1、leetcode121

    给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

    你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

    来源:力扣(LeetCode)
     

    class Solution {
        public int maxProfit(int[] prices) {
            int[][] dp = new int[prices.length][2];
            dp[0][0]=-prices[0];//买入状态 1代表卖出状态
            for(int i = 1;i<prices.length;i++){
                dp[i][0]=Math.max(dp[i-1][0],-prices[i]);
                dp[i][1]=Math.max(dp[i-1][0]+prices[i],dp[i-1][1]);
            }
            return dp[prices.length-1][1];
        }   
    }

    思路:每天存在两种状态,第一种持有状态,第二种是卖出状态。

    第一种状态来源于前一天买入的状态,或者是当天才买入的状态

    第二种状态来源于前一天卖出状态保持到今天,或者今天才卖出。

    dp[i][j],i代表是第几天,j是两种状态,分别是买入或者持有的最大利益值。

    Leetcode 122 买卖股票的最佳时机 II

     自己的解法:   
    public int maxProfit(int[] prices) { int[][] dp = new int[prices.length][2]; dp[0][0]=-prices[0]; int res = 0; for(int i = 1;i<prices.length;i++){ dp[i][0]=Math.max(dp[i-1][0],-prices[i]);//保持持有,或者今天持有 dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);//保持卖出,或者今天才卖出。 if(dp[i][1]>0){ res+=dp[i][1]; dp[i][0]=-prices[i]; dp[i][1]=0; } } return res; }

    算出每一天利润是否大于0,大于0我就卖出,累加利润。

    官方解法:

    public int maxProfit(int[] prices) {
            int[][] dp = new int[prices.length][2];
            dp[0][0]=-prices[0];//持有
            dp[0][1]=0;//不持有
            for(int i = 1;i<prices.length;i++){
                dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);//持有  保持昨天的持有状态,或者卖出状态减去购买今天的股票。
                dp[i][1]=Math.max(dp[i-1][1],dp[i][0]+prices[i]); //两个状态的转移,都是来自上一个状态,或者上一个合法状态到当前这个状态。
            }
            return dp[prices.length-1][1];
        }

    Leetcode 123 买卖股票的最佳时机 III

        public int maxProfit(int[] prices) {
                  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];
                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]);//当前卖出  
                dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);//第二次买入
                dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]);//第二次卖出 
            }
            return dp[prices.length - 1][4];
        }
    //

    第二次买入依赖于第一次卖出的状态,其实相当于第0天第一次买入了,第一次卖出了,然后在买入一次(第二次买入),那么现在手头上没有现金,只要买入,现金就做相应的减少。

    
    

    所以第二次买入操作,初始化为:dp[0][3] = -prices[0];

    
    

    同理第二次卖出初始化dp[0][4] = 0;

    设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

    注意:你不能同时参与多笔交易你必须在再次购买前出售掉之前的股票) 同一天买了又卖,就能解决上面的初始化问题。

    
    

    leetcode 188 买卖股票的最佳时机 IV

        public int maxProfit(int k, int[] prices) {
            if(prices.length==0){
                return 0;
            }
            int[][][] dp = new int[prices.length][k+1][2];
            for(int i = 0;i<=k;i++){
                //初始化 0代表是买入状态,1是代表卖出状态
                dp[0][i][0]=-prices[0];
            }
            for(int i = 1;i<prices.length;i++){
                for(int j = 1;j<=k;j++){
                    dp[i][j][0]=Math.max(dp[i-1][j][0],dp[i-1][j-1][1]-prices[i]); //当前是今天买入状态,或者昨天未持有,就要j-1笔
                    dp[i][j][1]=Math.max(dp[i-1][j][1],dp[i-1][j][0]+prices[i]);   //保持卖出,从上一个买入状态卖出。
                }
            }
            return dp[prices.length-1][k][1];
        }

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

                        int n = prices.length;
            if (n == 0) {
                return 0;
            }
            //状态一 0 持有股票 (第一种是保持买入,第二种是冷冻期,保持卖出)  保持买入该状态转移过来的,第二种冷冻期后买入第四种状态,冷冻期过来,或者状态2中保持卖出。
            //状态二 1 卖出股票:1、前一天就是状态 2 昨天是冷冻期 该状态转移过来的,和状态4转移过来的。
            //状态三 2 卖出股票,今天卖股票
            //状态四 3 冷冻期今天
    
            int[][] dp = new int[prices.length][4];
            dp[0][0] = -prices[0];//持有股票
            for (int i = 1; i < n; i++) {
                //持有股票,保持昨天的持有,今天购买  前一天不可能刚刚卖出,如果卖出就是冷冻期
                dp[i][0]=Math.max(dp[i-1][0],Math.max(dp[i-1][1],dp[i-1][3])-prices[i]);
                dp[i][1]=Math.max(dp[i-1][1],dp[i-1][3]);
                dp[i][2]=dp[i-1][0]+prices[i];
                dp[i][3]=dp[i-1][2];
                
                
            }
            return Math.max(Math.max(dp[prices.length-1][0],dp[prices.length-1][1]),Math.max(dp[prices.length-1][2],dp[prices.length-1][3]));
        }

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

        public int maxProfit(int[] prices, int fee) {
            int[][] dp = new int[prices.length][2];
            dp[0][0] = -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]); 
                dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]+prices[i]-fee);
            }
            return dp[prices.length - 1][1];
        }
  • 相关阅读:
    MySQL语句创建表、插入数据遇到的问题-20/4/18
    【Navicat】MySQL 8.0.17 数据库报2059错误
    MySQL 8.0.17 版安装 || Windows
    C#--Invoke和BeginInvoke用法和区别
    C#--params关键字
    C#--typeof() 和 GetType()区别
    C#--利用反射编写的SqlHelper类
    C#--反射基础
    C#--LINQ--2--LINQ高级查询
    C#--LINQ--1--初学LINQ基础和查询
  • 原文地址:https://www.cnblogs.com/Alei777/p/16482786.html
Copyright © 2020-2023  润新知