当前位置:   article > 正文

算法——买卖股票(动态规划)_买卖盘编程表达

买卖盘编程表达

买卖股票

准备总结一下做过的几道买卖股票的题目,还有几道还没来得及做,先把做过的做一个总结,以便日后忘了,留作复习使用。
题目难度又简到难。(一些题目直接参考的是官方题解)。有很多地方理解不到位或者是表述不清,但是还是先做个笔记,方便理解吧。

题目一 买卖股票的最佳时机

题目描述

在这里插入图片描述

解题思路

最大收益就是需要在较低的价格买入,较高的价格卖出。遍历数组,找到当前天数i之前的股票价格的最小值min,如果存在,则当前日期的收益为prices[i] - min;如果找不到,说明当前日期的股票价格是目前遍历过的数组元素中最低的,将min的值设置为当前日期的股票价格。
细节处理,在第一天时,只能买入股票或者是不做任何操作,而不能卖出股票,设置min初始值为Integer.MAX_VALUE,与prices[0]比较,初始值被修改为prices[0]。

代码

class Solution {
    public int maxProfit(int[] prices) {
        int res = 0;
        if(prices.length<2){
            return res;
        }
        int min = Integer.MAX_VALUE;
        for(int i=0;i<prices.length;i++){
            if(min>prices[i]){
                min = prices[i];
            }else{
                res = Math.max(res,prices[i] - min);
            }
        }
        return res;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

题目二 买卖股票的最佳时机2

题目描述

解题思路

与题目一相比,不同点在于股票交易的次数不受限制了,目的仍是追求最大利益。题目核心是贪心算法。
为了追求利益的最大化,我们在价格低点买入股票,在上涨的最高点卖出股票。假设我们在第i天买入,第i+1、i+2、……、i+j天都在上涨,我们在这几天都保持持有,不做卖出操作,遍历到第i+j+1天时,价格较第i+j天相比下降,则在第i+j天卖出,在第i+j+1天买入(如果第i+j+2天的价格较第i+j+1天就像下降,则选择在第i+j+2天买入)。
这样的过程实质相当于在价格数组找到多个连续递增的子序列。

代码

min记录的是买入时的价格,max记录的是卖出时的价格。

class Solution {
    public int maxProfit(int[] prices) {
           int profit = 0, max = prices[0], min = prices[0];
           if(prices.length<2)
           return profit;
        for(int i=1;i<prices.length;i++){
            if(prices[i]>prices[i-1])
            {
                max = prices[i];
                if(i==prices.length-1)
                {
                    profit = profit +max - min;
                }
            }
            else
            {
                profit = profit +max - min;
                max = prices[i];
                min = prices[i];
            }
        }
        return profit;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

可以对上述代码作出简化:

class Solution {
    public int maxProfit(int[] prices) {
        int res = 0;
        if(prices.length<2){
            return res;
        }
        for(int i=1;i<prices.length;i++){
            res+=Math.max(0,prices[i] - prices[i-1]);
        }
        return res;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

题目三 买卖股票的最佳时机含手续费

题目描述

在这里插入图片描述

解题思路

这道题相当于在题目二的基础上增加了手续费这一限制因素。
买卖股票这种题目其实可以记录两种状态,因为每天可以采取的措施就是买入和卖出两种,我们在这两种操作中选择利益最大的那个即可,其次理清题目的逻辑即可。
记录两种状态,第一种是买入buy(如果当前天数i的前一天不持有股票,则在第i天买入,需要用前一天的累计收益sell[i-1]减去成本prices[i];如前一天持有股票,则继续持有即可),记录的是当前日期第i天买入后的收益;第二种状态是卖出sell(如果当前日期第i天 的前一天手上不持有股票,则无法卖出,持有收益与前一天相同;如果前一天持有股票,则计算卖出的收益buy[i-1]+prices[i],同时减去手续费),记录的当前日期第i天卖出后的累计收益。
用计算式表达上述情况如下:
buy[i] = Math.max(buy[i-1],sell[i-1] - prices[i])
sell[i] = Math.max(buy[i-1]+prices[i]-fee,sell[i-1])
考虑边界问题,开始第一天,无法卖出,故将卖出的收益设置为sell[0] = 0,代表卖出收益为0,符合逻辑;在一天执行买入操作,则收益为buy[0] = -prices[0]。
最后的答案就是sell[prices.length-1],因为将所有的股票卖出,才会获得收益,手上没有股票才是最赚钱的。

代码

class Solution {
    public int maxProfit(int[] prices, int fee) {
        if(prices.length<2){
            return 0;
        }
        int []buy = new int[prices.length];
        int []sell = new int[prices.length];
        buy[0] = -prices[0];
        sell[0] = 0;
        for(int i=1;i<prices.length;i++){
            buy[i] = Math.max(buy[i-1],sell[i-1] - prices[i]);
            sell[i] = Math.max(buy[i-1]+prices[i]-fee,sell[i-1]);
        }
        return sell[prices.length-1];
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

题目四 买卖股票的最佳时机4

题目描述

在这里插入图片描述

解题思路

与题目三类似,记录买入与卖出两种状态。
限制条件是最多执行k笔交易,使用二维数组来记录买入和卖出状态,数组的第一维下标i代表当前日期第i天,第二维下标j代表目前已经完成了j笔交易(完成一笔交易的定义是从买入到卖出完成才算一笔交易,只买入未卖出则不算一笔交易)。
其余逻辑与第三题一致,表达式如下:
buy[i][j] = Math.max(buy[i-1][j],sell[i-1][j] - prices[i]);
第i天执行买入操作:buy[第i天][已完成了j笔交易] = Math.max(前一天已持有股票,买入收益与前一天保持一致;前一天没有买入记录,用当前卖出收益减去成本);
sell[i][j] = Math.max(buy[i-1][j-1]+prices[i],sell[i-1][j]);
第i天执行卖出操作:sell[第i天][已完成了j笔交易] = Math.max(前一天的买入收益加上当前的价格;前一天没有买入操作,继续保持前天的卖出收益)。
边界问题,第一天buy[0][0] = -prices[0],sell[0][0] = 0,其余buy[0][j]和sell[0][j]都设置为Integer.MIN_VALUE/2,这样做一是为了将这几个状态设置为不合法,不可能第0天就完成了数笔交易;第二除2是为了在之后的减法操作中防止溢出。
最后的结果是在最后一天的卖出记录中寻找最大值。

代码

class Solution {
    public int maxProfit(int k, int[] prices) {
        int res = 0;
        if(k==0||prices.length==0){
            return res;
        }
        int [][]buy = new int[prices.length][k+1];
        int [][]sell = new int[prices.length][k+1];
        buy[0][0] = -prices[0];
        sell[0][0] = 0;
        for(int i=1;i<=k;i++){
            sell[0][i] = Integer.MIN_VALUE/2;
            buy[0][i] = Integer.MIN_VALUE/2;
        }
        int n = prices.length;
        for(int i =1;i<n;i++){
            buy[i][0] = Math.max(buy[i-1][0],sell[i-1][0] - prices[i]);
            for(int j=1;j<=k;j++){
                buy[i][j] = Math.max(buy[i-1][j],sell[i-1][j] - prices[i]);
                sell[i][j] = Math.max(buy[i-1][j-1]+prices[i],sell[i-1][j]);
            }
        }
        for(int i=1;i<=k;i++){
            res = Math.max(res,sell[n-1][i]);
        }
        return res;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

题目五 买卖股票的最佳时机3

这道题目在写完上面几道题解后顺势完成的。

题目描述

在这里插入图片描述

解题思路

解题思路和上一题一样,只是将K固定为2.

代码

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length<2){
            return 0;
        }
        int [][]buy = new int[prices.length][3];
        int [][]sell = new int[prices.length][3];
        buy[0][0] = -prices[0];
        sell[0][0] = 0;
        for(int i=1;i<=2;i++){
            buy[0][i]=sell[0][i] = Integer.MIN_VALUE/2;
        }
        for(int i=1;i<prices.length;i++){
            buy[i][0] = Math.max(buy[i-1][0],sell[i-1][0] - prices[i]);
            for(int j=1;j<=2;j++){
                buy[i][j] = Math.max(buy[i-1][j],sell[i-1][j] -prices[i]);
                sell[i][j] = Math.max(buy[i-1][j-1]+prices[i],sell[i-1][j]);
               // System.out.println(buy[i][j]+","+sell[i][j]);
            }
        }
        int res = 0;
        int max = Math.max(sell[prices.length-1][1],sell[prices.length-1][2]);
        res = Math.max(0,max);
        return res;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/698469
推荐阅读
相关标签
  

闽ICP备14008679号