leetcode 188.买卖股票则最佳时机 IV

原题

188.买卖股票则最佳时机 IV
在这里插入图片描述

题解

方法一 动态规划

当然我们可以仿照leetcode123.买卖股票的最佳时机 III里面的方法来塑造一个三维的数组,三维的含义分别表示的是日期、完成交易的次数,以及现在持有的股数。按照惯例,我们要验证k是否大于最大可能的交易数目,可是遗憾的是,此方法缩小了k数目到一半的prices长度,仍然超内存。
(此方法空间复杂度是O((Math.min(k,p.l/2))^2),而由于运行过程需要遍历三维数组每一个元素,那么时间复杂度也一样)
失败的代码示例;

//超时超内存
class Solution {
    public int maxProfit(int k, int[] prices) {
        if(prices.length==0){return 0;}
        k=Math.min(k,prices.length/2);
        //三维分别表示,日期、完成的交易数(0-k)、手中持股数
        int daan=0;
        int ans[][][]=new int[prices.length][k+1][2];
        for(int i=0;i<prices.length;i++){
            for(int j=0;j<=k;j++){
                if(i==0){
                    ans[0][j][1]=-prices[0];
                }
                else{
                    if(j==0){
                        ans[i][0][1]=Math.max(ans[i-1][0][1],-prices[i]);
                    }
                    else{
                        ans[i][j][0]=Math.max(ans[i-1][j-1][1]+prices[i],ans[i-1][j][0]);
                        ans[i][j][1]=Math.max(ans[i-1][j][0]-prices[i],ans[i-1][j][1]);
                    }
                }
            }
        }
        for(int i=0;i<=k;i++){
            daan=Math.max(daan,ans[prices.length-1][i][0]);
        }
        return daan;
    }
}

既然这样,我们需要尽可能先减少动态规划中的空间消耗。我们何不不考虑日期,而只考虑交易完成的次数和手中的持股情况?
那么算法就变成了,建立一个二维数组,两个维度分别表示的是完成的交易数、手中的持股数。这样的话我们只需要消耗O(Math.min(k,p.l/2))的空间,时间复杂度是O(p.l*Math.min(k,p.l/2))
本思路java代码示例:

/*
@v7fgg
执行用时:170 ms, 在所有 Java 提交中击败了6.35%的用户
内存消耗:39.6 MB, 在所有 Java 提交中击败了11.11%的用户
2020年7月13日 14:02
*/
class Solution {
    public int maxProfit(int k, int[] prices) {
        if(prices.length==0||k==0){return 0;}
        k=Math.min(k,prices.length/2);//防止超内存,最多k次交易
        int daan=0;
        //ans[a][b]表示的是在某一天的时候,我已经完成了a此交易,手里攥着b股
        int[][] ans=new int[k+1][2];
        for(int i=0;i<k;i++){
            ans[i][1]=-prices[0];
        }
        for(int j=1;j<prices.length;j++){
            for(int i=k;i>0;i--){                
                ans[i][1]=Math.max(ans[i][0]-prices[j],ans[i][1]);   
                ans[i][0]=Math.max(ans[i-1][1]+prices[j],ans[i][0]);                            
            }
            ans[0][1]=Math.max(-prices[j],ans[0][1]);
        }
        for(int i=0;i<=k;i++){
            daan=Math.max(daan,ans[i][0]);
        }     
        return daan;
    }
}

改为一维数组后,代码如下:

/*
@v7fgg
执行用时:437 ms, 在所有 Java 提交中击败了5.02%的用户
内存消耗:40 MB, 在所有 Java 提交中击败了11.11%的用户
2020年7月10日 16:48
*/
class Solution {
    public int maxProfit(int k, int[] prices) {
        if(prices.length==0||k==0){return 0;}
        k=Math.min(k,prices.length/2);//防止超内存
        int[] ans=new int[2*k];
        int daan=0;
        for(int i=0;i<2*k;i+=2){
            ans[i]=-prices[0];
        }
        for(int j=1;j<prices.length;j++){
            for(int i=2*k-1;i>=1;i--){
                if(i%2==0){ans[i]=Math.max(ans[i-1]-prices[j],ans[i]);}
                else{ans[i]=Math.max(ans[i-1]+prices[j],ans[i]);}
            }
            ans[0]=Math.max(ans[0],-prices[j]);
        }
        for(int i=0;i<2*k;i++){
            daan=Math.max(daan,ans[i]);
        }
        return daan;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

可爱抱抱呀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值