leetcode Q123 Best Time to Buy and Sell Stock

首先贴一个discuss区写的不错的解释(引用一下)

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/discuss/111150/How-to-achieve-best-solution-with-O(n)-O(1)-step-by-step

这是是其中O(n^2)的解法:

public int maxProfit(int[] prices) {
        if(prices == null || prices.length == 0) return 0;
        int length = prices.length;
        int[] oneProfit = new int[length];
   
        //minimum value from 0 to i(included)
        int minSoFar = prices[0];
        for(int i = 1; i < length; i++){
            oneProfit[i] = Math.max(oneProfit[i - 1], prices[i] - minSoFar);
            minSoFar = Math.min(minSoFar, prices[i]);
        }
        
        int[] twoProfit = new int[length];
        
        for(int i = 1; i < length; i++){
            int max = twoProfit[i - 1];
            for(int j = 0; j < i; j++){
                max = Math.max(max, prices[i] - prices[j] + oneProfit[j]);
            }
            twoProfit[i] = max;
        }
        return twoProfit[length - 1];
       
    }

其中关于这一段的解释其实我觉得不够准确

max = Math.max(max, prices[i] - prices[j] + oneProfit[j])

原作者对于交易两次的思路是,第i天卖或者不卖,不卖的话价值却决于上一个max,卖的话,我们就要找从1到i天中一个切分点,分别交易两次,那么这里应该是写成:

max = Math.max(max, prices[i] - prices[j] + oneProfit[j-1])

因为第j天你不可以同时买入和卖出,如果代码改成这样的话,最后结果我们要和oneProfit比较大小从而返回结果,因为此时twoProfit代表的意思是恰好交易两次的情况下,得到的最大值。

 

但是,原来的代码是可以得到正确的结果的,我们假设不是测试用例的问题,那么说明,原有的代码中twoProfit[i]的意思是前i天中最多交易两次可以得到的最大利润,这样就不存在漏解的情况。

我的基本的理解是,oneProfit[i]的值中,可能是第i天卖出的,也可能不是,那么我们针对这两种情况下分别看会怎么执行:

  1. 如果第i天没有卖出,那么twoProfit得到的值就是交易两次情况下得到的profit
  2. 如果卖出了,那么twoProfit实际得到的值是交易一次情况下的profit

最后一遍遍历下来,我们得到了前i天情况下,交易一次可以得到的最大值和恰好交易两次情况下的最大值中的最大值,也就是说twoProfit[i]的值的意义变为了最多两次交易情况下前i天可以得到的最大利润,这其实也就是我们修改代码之后加上的部分,实际并没有漏解,但是毫无疑问,这样写起来就漂亮多了,而且,后面改进算法成时间O(n),空间O(1)情况下,python直接四行代码可以解决问题

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章