DP

121. Best Time to Buy and Sell S

2017-04-08  本文已影响72人  DrunkPian0

09/04/2017

这题用局部最优解和全局最优解的标准套路来想吧,这就是dp啊。递推公式:

local[i+1]=max(local[i]+prices[i+1]-price[i],0), global[i+1]=max(local[i+1],global[i])

理解起来比较清晰:

    public int maxProfit(int[] prices) {
        if (prices.length < 2) return 0;
        //当天卖出的最大profit
        int local = 0;
        int global = 0;
        for (int i = 1; i < prices.length; i++) {
            //今天必须要交易,可以是买或卖。
            //对于1,2,3,0,2这样的,第三天赚卖了两块,第四天卖了比第三天要亏三块,
            //总共profit就是2-3=-1,那就不如之前什么都没发生,从今天的价格开始买,local = 0。但是虽然重新开始了,之前的最大利润被保存起来了,从0开始再比。
            local = Math.max(local + prices[i] - prices[i - 1], 0);
            global = Math.max(global, local);
        }
        return global;
    }

一道题(即便是简单题),如果不按照应有的套路来思考的话,你会在写出一些野路子的code之后commit时发现漏掉了很多test cases。之前做过一个关于括号的题目就是这样。今天这道题也是如此。
我一开始写的是一个O(n*n)的双重for循环搜索的方法,看似是没什么问题的,但是提交的时候TLE了,就不谈了。

//TLE:BRUTE FORCE
//    public int maxProfit(int[] prices) {
//        int res = 0;
//        for (int i = 1; i < prices.length; i++)
//            for (int j = 0; j < i; j++) {
//                res = prices[i] - prices[j] > res ? prices[i] - prices[j] : res;
//            }
//        return res ;
//    }

然后我其实感觉这题不需要用DP,只要维护两个变量,一个是当前最大收益,一个是最大收益的那一天的price,然后如果当天的price比取得最大收益那天的price还要高,就更新这两个值就行了;但是这么做没有办法重新选择一个新的买入价格,一旦获取了一个买入和卖出的价格就永远以这次为基准了,漏掉了一种test case , 下面这种,最大收益的那天的price永远停留在2:

[2,1,2,1,0,1,2]

正确做法:不过这个没有用DP..

    public int maxProfit(int[] prices) {
        if (prices.length < 2) return 0;
        if (prices.length == 2) return prices[1] - prices[0] > 0 ? prices[1] - prices[0] : 0;

        //当前最低价
        int minPrice = prices[0];
        //当前最大收益
        int maxProfit = 0;
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] < minPrice) minPrice = prices[i];
            maxProfit = Math.max(prices[i] - minPrice, maxProfit);
        }
        return maxProfit;
    }

dp的方法覃超讲了。

上一篇下一篇

猜你喜欢

热点阅读