LeetCode简单篇----11----买股票的最佳时机Ⅱ

纵饮孤独 提交于 2020-02-01 23:54:14

目录

一、需求

二、暴力递归法

2.1  思路分析

2.2  代码实现

2.3  复杂度分析

三、峰谷法

3.1  思路分析

3.2  代码实现

3.3  复杂度分析

四、峰谷法改进(贪心算法)

4.1  思路分析    

4.2  代码实现

4.3  复杂度分析

五、动态规划法

5.1  思路分析

5.2  代码实现

5.3  复杂度分析

六、参考地址


一、需求

      A:给定一个数组,它的第i个元素是一支给定股票第i天的价格;

      B:设计一个算法计算能获取的最大利润,可以尽可能完成更多交易(多次买卖一支股票);

      C:注意你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)

二、暴力递归法

2.1  思路分析

      A:假设prices = [7,1,5,3,4,6,...];

      B:假设第1天买入,第2天卖出,则最大利润为prices[1]-prices[0]+[5,3,4,6,...]的最大利润;

      C:假设第1天买入,第3天卖出,则最大利润为prices[2]-prices[0]+[3,4,6,...]的最大利润;

      D:归纳推理

        a:假设第i天买入,那么0 <= i < prices.length;

        b:假设第j天卖出,那么i+1 < j < prices.length;

        c:最大利润=prices[j]-prices[i]+calculate(prices,j+1);

      E:递归的终止条件是什么呢?

        a:上面D中c步骤是关键,j+1会当作参数传递给calculate方法,也就是每次递归,这个参数都要变大,

          直到prices[j]是最后后一天时,j+1就是当前数组的长度,然后返回0;

      F:递归的规律是什么呢?

        a:当买入的价格低于要售出的价格时,开始递归,规律就是D中的c,并更新在某一天买入时,能获得的

           最大利润;

      G:比较每天买入能够获得的最大利润,并更新;

      H:注意,递归太深的话,响应会超时;

2.2  代码实现

class Solution {
    public int maxProfit(int[] prices) {
        return calculate(prices, 0);
    }
    //定义方法
    public int calculate(int[] prices,int s) {
        int max = 0;
        //递归的终止条件
        if(s >= prices.length) {
            return 0;
        }
        for(int i = s; i < prices.length; i++) {
            //更新某天买入能获得的最大利润
            int maxprofit = 0;
            for(int j = i+1; j < prices.length; j++) {
                if(prices[i] < prices[j]) {
                    int profit = calculate(prices,j+1)+prices[j]-prices[i];
                    if(profit > maxprofit) {
                        maxprofit = profit;
                    }
                }
            }
            if(maxprofit > max) {
                max = maxprofit;
            }
        }
    return max;
    }
}

2.3  复杂度分析

      A:时间复杂度为O(n^n),调用递归函数n^n方次;

      B:空间复杂度为O(n),递归调用的深度为n;

三、峰谷法

3.1  思路分析

      A:因为交易次数可以是多次,故最大利润=多次交易的(波峰-波谷)的和;

      B:使用i来遍历天数,i从0开始,考虑到在确定波谷/峰的时候,需要比较prices[i]和prices[i+1],

         那么i最多只能遍历到倒数第2天,也就是0<=i<prices.length-1;

      C:既然要确定连续的波谷波峰,那就需要采用循环的方式,找到那个最低的谷;

          a:当前第i天的价格要高于第i+1天的价格,则i++;

          b:i最多遍历到倒数第2天,不然假设遍历到倒数第2天,i++后,数组就越界了;

3.2  代码实现

public int maxProfit(int[] prices) {
        //定义相关变量
        int profit = 0;
        int i = 0;
        int valley = 0;
        int peak = 0;

        //寻找波谷和波峰,并求最大利润
        while(i < prices.length - 1) {
            //找到连续的谷和峰
            //找到波谷
            while(i < prices.length - 1 && prices[i] >= prices[i+1]) {
                i++;
            }
            valley = prices[i];
            //找到波峰
            while(i < prices.length - 1 && prices[i] <= prices[i+1]) {
                i++;
            }
            peak = prices[i];
            //更新最大利润
            profit += peak - valley;
        }
        return profit;
    }

3.3  复杂度分析

       A:因为从头到尾,是i从0遍历到了倒数第二个元素,所以时间复杂度为O(n);

       B:只使用了常量的空间,空间复杂度为O(1);

四、峰谷法改进(贪心算法)

4.1  思路分析    

       A:在峰谷法的基础上,我们把每一次寻找到的连续的谷和峰分解成了很多小段;

       B:在求谷的过程中,可能连续2天都在下降,在求峰的过程中,可能连续3天都在上升;

       C:利用循环,从第1天开始,到最后一天,1<=i<prices.length;

          a:若第i天的价格要大于前1天的价格,那就说明有利可图,相当于波谷到波峰上升的那一段;

          b:然后到了波峰到波谷下降的一段,没啥利润了,就直接对i++;

          c:然后再从波谷到波峰,这样结束后,最大利润也就出来了;

4.2  代码实现

public int maxProfit(int[] prices) {
        int profit = 0;
        for(int i = 1; i < prices.length; i++) {
            if(prices[i] > prices[i-1]) {
                profit += prices[i] - prices[i-1];
            }
        }
    return profit;
    }

4.3  复杂度分析

       A:时间复杂度为O(n);

       B:只使用了常量的空间,空间复杂度为O(1);

五、动态规划法

5.1  思路分析

       A:目前分析不出来;

5.2  代码实现

public int maxProfit(int[] prices) {
        int len = prices.length;
        //len为1或0,最大利润为0
        if (len < 2) {
            return 0;
        }
        // 0:持有现金
        // 1:持有股票
        int[][] dp = new int[len][2];

        dp[0][0] = 0;
        dp[0][1] = -prices[0];

        for (int i = 1; i < len; i++) {
            //第i天持有现金=昨天就持有的现金 或者 将昨天的股票在今天卖出得到的现金 的最大值
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            //第i天持有股票=昨天就持有股票 或者  用昨天的现金在今天买入股票 的最大值;
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
        }
        return dp[len - 1][0];
    }

5.3  复杂度分析

       A:时间复杂度为O(n);

       B:二维数组的第二维是常量,空间复杂度为O(n);

六、参考地址

       A:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/tan-xin-suan-fa-by-liweiwei1419-2/

       B:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode/

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!