zoukankan      html  css  js  c++  java
  • 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;
        }
  • 相关阅读:
    (转)mybatis-plus入门
    (转)mybatis数据库物理分页插件PageHelper
    (转)mybatis热加载(依赖mybatis-plus插件)的实现
    The walking dead
    JDBC编程六部曲
    MySQL时区错误导致server time zone value '&#214;&#208;&#185;&#250;&#177;&#234;&#215;&#188;&#202;&#177;&#188;&#228;' 错误
    SpringMVC-Helloworld 的归纳理解
    Helloworld——SpringMVC
    starting Tomcat v8.5 at localhost has encountered a problem
    我的第一个SpringProject——HelloWorld
  • 原文地址:https://www.cnblogs.com/niuyourou/p/12866400.html
Copyright © 2011-2022 走看看