Leetcode - Best Time to Buy and Sell Stock III

Leetcode - Best Time to Buy and Sell Stock III_第1张图片
Paste_Image.png

My code:

public class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0 || prices.length == 1)
            return 0;
        int[] left = new int[prices.length];
        int[] right = new int[prices.length];
        getMaxProfit(left, right, prices);
        int[] sum = new int[prices.length];
        int max = 0;
        for (int i = 0; i < prices.length; i++) {
            sum[i] = left[i] + right[i];
            if (max < sum[i])
                max = sum[i];
        }
        return max;
    }
    
    private void getMaxProfit(int[] left, int[] right, int[] prices) {
        int min = prices[0];  //represent the min prices
        int max = 0;  //represent the max profit
        for (int i = 1; i < prices.length; i++) {
            int temp = prices[i] - min;
            if (temp < 0) {
                left[i] = max;
                min = prices[i];
            }
            else if (temp <= max)
                left[i] = max;
            else {
                left[i] = temp;
                max = temp;
            }
        }
        
        int rightMax = prices[prices.length - 1];
        int profitMax = 0;
        for (int i = prices.length - 2; i >= 0; i--) {
            int temp = rightMax - prices[i];
            if (temp < 0) {
                right[i] = profitMax;
                rightMax = prices[i];
            }
            else if (temp < profitMax)
                right[i] = profitMax;
            else {
                right[i] = temp;
                profitMax = temp;
            }   
        }
    }
}

My test result:

Leetcode - Best Time to Buy and Sell Stock III_第2张图片
Paste_Image.png

这次作业没能有自己的思路,然后看了一篇博客,写的很好,思路很明确清晰,于是我按照这个思路自己写了出来。
顺便把这个系列的题目总结下吧。
第一题,就是给你一串数,然后买进卖出,最多只做一次交易,求最大利润。
那么,其实就是,DP,从 i = 1开始,不断地向前递进,每一次,
计算下prices[i] - min 的值,
如果大于max,那就设这个值为max,
如果小于max但>=0,则保持max, min不变。
如果小于0,则更新min为当前值。
所以说,max代表的是当前范围内的最大利润,而min表示当前范围内的最大利润中,买进的价格。不一定是当前范围内的最小值。
然后遍历一遍即可以得出结果。

第二题,同样是一串数,买进卖出。但是,允许无限次交易,求最大利润。
因为允许无限次交易。可以设置一个数组diff[],用来记录前后两个数的差值,
如果大于0,则全部累加到变量max上。
如果小于0,就不加。
遍历结束后,该max即为最大利润。
为什么?
比如,2, 3, 5, 7
如果是递增数列,那么
7 - 2 = (3- 2) + (5- 3) + (7 - 5)
如果出现递减的,比如,2, 1, 5, 3, 7
这里就有一个注意点,如果是无限次交易,那我就是买进1,卖出5,然后买进3卖出7,这样赚的最多,所以可以累加。可以把每一次出现的递减点,当做是新的一次交易的买进值。
但是,如果限制只允许一次交易,那么就该是,买进1,卖出7。即需要采用第一题的思路了。

第三题,同样是一串数,买进卖出,但是,只允许最多两次交易,求最大利润。
所以,可以把数组一切为2,[0, i] 为第一次交易, [i, prices.length - 1] 为第二次交易。
特定到i点时,可在i点把货物卖出,作为[0, i]区域的终结,然后再i点把货物买入, 作为[i, prices.length - 1]区域的开始,

于是可以设置两个数组,left[], right[]
left[i] 表示 [0, i] 这么一段区域内,交易一次最大的利润。可以用第一题的算法来解决。
right[i] 表示 [i, prices.length - 1] 这么一段区域内,交易一次最大的利润,可以反过来用第一题的思路来解决。
left[i] + right[i] 即等于在第i天时为分界点进行两次交易的最大利润值。
然后遍历获得这些分界点利润最大值中的最大值,即为我们需要的最大利润。
我觉得文章里有句话说的挺对的,
看来以后碰到与2相关的问题,一定要想想能不能用二分法来做!

Leetcode - Best Time to Buy and Sell Stock III_第3张图片
Paste_Image.png

http://blog.csdn.net/fightforyourdream/article/details/14503469

第四题,等等更新。
放弃吧。。。。感觉好他妈复杂。具体做法有时间还是看上面那个网页对应的文章。
最后还是测试过了,但主要还是拷贝了代码,这道题目真的很难啊。。。逻辑复杂,代码简单。需要考虑的一个情况是,
当 k >= prices.length, 的时候,就直接用
Best Time to Buy and Sell Stock II 的无限次交易方法来做,测试就过了。http://www.cnblogs.com/grandyang/p/4295761.html

**
总结:DP 以后碰到与2相关的问题,一定要想想能不能用二分法来做!
老爸好像吃坏肚子了,然后拉肚子之后还发烧,感觉爸妈的身体真的没以前好了,如果我不在家,他们。。。不能去想了。要想走出去,必须得有牺牲。
我们不是贵族阶级。
**

Anyway, Good luck, Richardo!


public class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0 || prices.length == 1)
            return 0;
        int[] profits = new int[prices.length];
        int[] left = new int[prices.length];
        int[] right = new int[prices.length];
        
        process(prices, left, right);
        for (int i = 0; i < profits.length; i++)
            profits[i] = left[i] + right[i];
        Arrays.sort(profits);
        return profits[profits.length - 1];
    }
    
    private void process(int[] prices, int[] left, int[] right) {
        left[0] = 0;
        right[right.length - 1] = 0;
        
        int min = prices[0];
        for (int i = 1; i < left.length; i++) {
            left[i] = Math.max(left[i - 1], prices[i] - min);
            min = Math.min(min, prices[i]);
        }
        
        int max = prices[prices.length - 1];
        for (int i = right.length - 2; i >= 0; i--) {
            right[i] = Math.max(right[i + 1], max - prices[i]);
            max = Math.max(max, prices[i]);
        }
    }
}
      ---- 09/23/2015 23:17

Anyway, Good luck, Richardo!


My code:

public class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length <= 1)
            return 0;
        int max = 0;
        int[] profits = new int[prices.length];
        int buy = prices[0];
        /** 1: [0, i];   2: [i + 1, prices.length - 1] 
         * scan for transaction 1, [0, i], i++
         */
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] >= buy) {
                max = Math.max(max, prices[i] - buy);
            }
            else {
                buy = prices[i];                
            }
            profits[i] = max;
        }
        
        /** scan for tracnsaction 2, [i + 1, prices.length - 1], i-- */
        int sell = prices[prices.length - 1];
        max = 0;
        for (int i = prices.length - 2; i >= 0; i--) {
            if (prices[i + 1] <= sell) {
                max = Math.max(max, sell - prices[i + 1]);
            }
            else {
                sell = prices[i + 1];
            }
            profits[i] += max;
        }
        Arrays.sort(profits);
        
        return profits[profits.length - 1];
    }
}

一开始做的超时了。因为有许多重复操作。
然后改了下。做了出来,没看答案。虽然原来的做法还有些印象。

Anyway, Good luck, Richardo!

差不多的思路。
今天找人投了 amazon, ea, 还有校招的 two sigma
全职之战开始了。
好运。

Anyway, Good luck, Richardo! -- 08/19/2016

你可能感兴趣的:(Leetcode - Best Time to Buy and Sell Stock III)