买卖股票最佳时机系列算法总结

leetcode121

 某一天买入股票,未来任意一天卖出,只卖一次,求最大利润

思路:双指针i和j,当i所对应的股票的值小于j所对应的股票的值时记下price[j]-price[i]等于盈利的钱,然后j++,再次比较二者,盈利的钱需要和上次盈利的钱比较保证记录下来的盈利是最大的。如果i所对应的股票的值大于j所对应的股票的值,则说明出现亏损,需要将i变成j,再j++。

完整代码如下:

class Solution {
    public int maxProfit(int[] prices) {
        int i=0;
        int j=1;
        int max=0;
        while (j<prices.length){
            if(prices[j]-prices[i]>0){
                max=Math.max(max,prices[j]-prices[i]);
                j++;
            }else {
                i=j;
                j++;
            }
        }
        return max;
    }
}

leetcode122

某一天买入股票,未来任意一天卖出,只能卖了再买,但可以买卖多次,并允许同一天卖出后再买入,求最大利润

思路:贪心算法,只要买入的价格比卖出的底即有收益就卖,卖完就买。i和j的距离始终是1。

完整代码如下:

class Solution {
    public int maxProfit(int[] prices) {
        int i=0;
        int j=1;
        int sum=0;
        while (j<prices.length){
            if(prices[j]-prices[i]>0){
                sum=sum+(prices[j]-prices[i]);
              
            }
            i++;
            j++;
        }
        return sum;
    }
}

 leetcode714

某一天买入股票,未来任意一天卖出,只能卖了再买,但可以买卖多次,不允许同一天卖出后再买入,每笔交易有手续费,求最大利润

思路:动态规划,如果按照上一题的思路,只要有利润就卖,那么可能导致多次的手续费。准备两个数组,一个是买数组,一个是卖数组。

完整代码如下:

//没有降维
class Solution {
    public int maxProfit(int[] prices, int fee) {
        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(sell[i-1], buy[i-1]+prices[i]-fee);
        }
        return sell[prices.length-1];
    }
}

//降维
class Solution {
    public int maxProfit(int[] prices, int fee) {
        int buy;
        int sell;
        buy=-prices[0];
        sell=0;

        for (int i = 1; i < prices.length; i++) {
            buy=Math.max(buy, sell-prices[i]);
            sell=Math.max(sell, buy+prices[i]-fee);
        }
        return sell;
    }
}

leetcode309 

某一天买入股票,未来任意一天卖出,可以买卖多次,卖出后只能隔天再买入,求最大利润

第一天买和卖还有第二天的买需要特别处理,因为第二天的买需要由前面天的卖剩下的利润决定,但是目前才第二天所以没有前两天的卖,因此默认剩下的利润就是0。

完整代码如下:

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length==1)return 0;
        int [] buy=new int[prices.length];
        int [] sell=new int[prices.length];
        buy[0]=-prices[0];
        sell[0]=0;
        buy[1]=Math.max(-prices[0],-prices[1]);
        sell[1]=Math.max(sell[0],buy[0]+prices[1]);
        for (int i = 2; i < prices.length; i++) {
            buy[i]=Math.max(buy[i-1], sell[i-2]-prices[i]);
            sell[i]=Math.max(sell[i-1], buy[i-1]+prices[i]);
        }
        return sell[prices.length-1];
    }
}

leetcode123

某一天买入股票,未来任意一天卖出,只能先卖再买,最多买卖两次,求最大利润

两次就用两对buy和sell,第一对用来记录第一次买卖的,第二对用来记录第二次买卖的。需要注意由于第二天不可产生第二次卖故第二次买卖在第二天的记录和第一次买卖是一样的。

完整代码如下:

class Solution {
    public int maxProfit(int k, int[] prices) {
        int buy1 = Integer.MIN_VALUE;
        int buy2 = Integer.MIN_VALUE;
        int sell1 = 0;
        int sell2 = 0;
        for (int price : prices) {
            buy1 = Math.max(buy1, -price);
            sell1 = Math.max(sell1, buy1 + price);
            buy2 = Math.max(buy2, sell1 - price);
            sell2 = Math.max(sell2, buy2 + price);
        }
        return sell2;
    }
}

leetcode188

 某一天买入股票,未来任意一天卖出,只能先卖再买,最多买卖K次,求最大利润

 两次是用两对,k次就用k对,那么我们就使用buy数组和sell数组长度为k。

完整代码如下:

class Solution {
    public int maxProfit(int k, int[] prices) {
        int []buy = new int[k];
        int []sell = new int[k];
        Arrays.fill(buy,Integer.MIN_VALUE);
        
        for (int price : prices) {
            buy[0] = Math.max(buy[0], -price);
            sell[0] = Math.max(sell[0], buy[0] + price);
            for (int i = 1; i < k; i++) {
                buy[i]=Math.max(buy[i],sell[i-1]-price);
                sell[i]=Math.max(sell[i],buy[i]+price);
            }
        }
        return sell[k-1];
    }
}

算法学习自黑马的数据结构与算法~

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值