买卖股票2.买卖股票的时机(可多次交易)

可无数次交易(必须交易完成后再进行)

因为可以多次交易,所以和1的区别只有状态方程不同(今天买股的情况
如果今天结束后不持股,则可能是昨天持股,今天卖了,也可能是昨天就不持股。
如果今天结束后持股,可能是昨天就持股,也可能是昨天没持股,今天持股,这个就很只能买一次有区别了,由于是今天买的,而且能多次买,如果是买卖股票只能一次的话,那就只能-prices[i],为什么,因为之前的dp[i-1][0]肯定是0,因为都没买过,-prices[i]自然就是价格了。
而可多次交易的话,可能是昨天卖掉,今天买的,则昨天卖掉是有利润的尾dp[i-1][0],则今天买之后为dp[i-1][0]-prices[i];

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len < 2) {
            return 0;
        }
        int[][] dp = new int[len][2];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < len; 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]);
        }
        return dp[len - 1][0];
    }
}

最多可交易两次,必须一次结束后再下一次

需要有一个新的值来记录交易次数,只关注发生交易的时候,不用关心没有发送交易的时候,所以定义交易次数为1和2的时候就行。

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len < 2) {
            return 0;
        }
        int[][][] dp = new int[len][2][3];
        dp[0][0][1]=0;
        dp[0][1][1] = -prices[0];
        dp[0][0][2] = 0;
        dp[0][1][2] = -prices[0];
        for (int i = 1; i < len; i++) {//不用管没有发生交易,只管发生交易的就可以
            dp[i][0][1] =Math.max(dp[i-1][0][1],dp[i-1][1][1]+prices[i]);
            dp[i][0][2] =Math.max(dp[i-1][0][2],dp[i-1][1][2]+prices[i]);
            dp[i][1][1] =Math.max(dp[i-1][1][1],dp[i-1][0][0]-prices[i]);
            dp[i][1][2] =Math.max(dp[i-1][1][2],dp[i-1][0][1]-prices[i]);
        }
        return dp[len-1][0][2];
    }
}

最多可交易k次

因为一次交易最少要两天,所以交易的次数最多为k=len/2,如果k大于这个值,那就等于第二个问题,如果k小于这个值,就赋值k次初值,每一天都循环k次赋值即可。

class Solution {
    public int maxProfit(int k, int[] prices) {
        int len = prices.length;
        if (len < 2) {
            return 0;
        }
        if(k>=len/2)return maxProfit(prices);
        int[][][] dp = new int[len][2][k+1];
        for (int i = 1; i <= k; i++) {
            dp[0][0][i] = 0;
            dp[0][1][i] = -prices[0];
        }
        for (int i = 1; i < len; i++) {//不用管没有发生交易,只管发生交易的就可以
            for(int j=k;j>0;j--){
                dp[i][0][j] =Math.max(dp[i-1][0][j],dp[i-1][1][j]+prices[i]);
                dp[i][1][j] =Math.max(dp[i-1][1][j],dp[i-1][0][j-1]-prices[i]);
            }
        }
        return dp[len-1][0][k];
    }
     public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0) {
            return 0;
        }
        int length = prices.length;
        int[][] dp = new int[length][2];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < 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]);
        }
        return dp[length - 1][0];
    }
}

可交易无数次,但有冷冻期

在第一天卖掉股票后,第二天不能买,所以在今天有股票时,如果是今天买的,就不能算昨天没有了,而是算前天没有。

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len < 2) {
            return 0;
        }
        int[][] dp = new int[len][2];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < len; 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],(i>=2?dp[i-2][0]:0) -prices[i]);
        }
        return dp[len - 1][0];
    }
}

可交易无数次,但有手续费

只要在买入时加个手续费即可

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int len = prices.length;
        if (len < 2) {
            return 0;
        }
        int[][] dp = new int[len][2];
        dp[0][0] = 0;
        dp[0][1] = -fee-prices[0];
        for (int i = 1; i < len; 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[len - 1][0];
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值