leetcodeFace63 股票的最大利润 传统解法到峰谷法的演进过程

Posted 牛有肉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcodeFace63 股票的最大利润 传统解法到峰谷法的演进过程相关的知识,希望对你有一定的参考价值。

  很多清奇的解法不是靠拍脑袋一蹴而就的,而是随着传统解法一步一步优化来的。刷题时不需要经常焦虑自己没有创新毒辣的解题思路,应该从传统解法开始,考虑当前解法有什么可优化的点,并去实现它们。

  最容易想到的自然是暴力法,我们假设每个元素都可以作为买入元素的前提下,再假设在其之后的每个元素尝试卖出,纪录最大差值即可:

    public final int maxProfit(int[] prices) {
        int re = 0;
        int length = prices.length;
        for (int i = 0; i < length - 1; i++) {
            for (int j = i + 1; j < length; j++) {
                int temp = prices[j] - prices[i];
                if (temp > 0) {
                    re = Math.max(re, temp);
                }
            }
        }
        return re;
    }

  然后我们想办法对问题进行分治,找到暴力法中可重复使用的计算部分进行缓存,避免重复计算。问题规模由 prices 的长度决定,我们按照其长度分割问题。G(flag) 为前 flag 天可得最大利润,则状态转移方程为 G(flag) = Max { G(flag-1) , prices[flag]-min(prices[0]...prices[flag]) }:

   /**
     * @Author Nxy
     * @Date 2020/5/10 23:40
     * @Description G(flag) 为前 flag 天可得最大利润
     * G(flag)= Max { G(flag-1) , prices[flag]-min(prices[0]...prices[flag]) }
     * 我们用一个两元素数组做为返回值,第一个元素为 prices 在 0-flag 最小值,第二个元素为最大利润
     */
    public final int maxProfitDP(int[] prices) {
        if (prices == null || prices.length == 0) {
            return 0;
        }
        int[][] cache = new int[prices.length + 1][2];
        int[] re = maxProfitDP(prices, prices.length - 1, cache);
        return re[1];
    }

    public final int[] maxProfitDP(int[] prices, int flag, int[][] cache) {
        if (flag == 0) {
            return new int[]{prices[0], 0};
        }
        if (cache[flag][1] != 0) {
            return cache[flag];
        }
        int[] beforePrice = maxProfitDP(prices, flag - 1, cache);
        int newMinCost = Math.min(beforePrice[0], prices[flag]);
        int nowPrice = prices[flag] - newMinCost;
        int[] returnNums = new int[2];
        returnNums[0] = newMinCost;
        returnNums[1] = Math.max(beforePrice[1], nowPrice);
        cache[flag] = returnNums;
        return returnNums;
    }

  将带缓存的分治转化为递推表示,得到 DP 解法:

    public final int maxPricesDP2(int[] prices) {
        int length = prices.length;
        int[][] cache = new int[length][2];
        cache[0] = new int[]{prices[0], 0};
        for (int i = 1; i < length; i++) {
            int newMinCost = Math.min(cache[i - 1][0], prices[i]);
            int maxPrice = Math.max(cache[i - 1][1], prices[i] - newMinCost);
            cache[i] = new int[]{newMinCost, maxPrice};
        }
        return cache[length - 1][1];
    }

  从 DP 我们看到,其实没必要用缓存数组,只需要两个变量分别记录前 flag 个元素中的最小值和前 flag-1 个元素的最大利润即可。这样我们得到了峰谷法解法:

    public final int maxPrices(int[] prices) {
        int length = prices.length;
        if (length == 0) {
            return 0;
        }
        int minCost = prices[0];
        int maxPrices = 0;
        for (int i = 1; i < length; i++) {
            minCost = Math.min(minCost, prices[i]);
            maxPrices = Math.max(maxPrices, prices[i] - minCost);
        }
        return maxPrices;
    }

 

以上是关于leetcodeFace63 股票的最大利润 传统解法到峰谷法的演进过程的主要内容,如果未能解决你的问题,请参考以下文章

剑指[63]_股票的最大利润问题 ; 力扣[122]_买卖股票的最大利润时机 II

剑指Offer面试题63. 股票的最大利润

剑指Offer面试题63. 股票的最大利润

LeetCode 面试题63. 股票的最大利润

LeetCode 面试题63. 股票的最大利润

剑指 Offer 63. 股票的最大利润