leetcode problem - 123. Best Time to Buy and Sell Stock III

Keywords: IE

Title:

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most two transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

Continue the previous two topics, this topic is only two transactions, the first thought is to find the maximum profit of the first transaction, and then the second transaction, the two transactions can not overlap. So we use an array to save the maximum profit at each step of the first traversal, and then reverse traversal to find the profit of the second transaction. Code in:

    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len < 2)
            return 0;
        int [] maxBefore = new int[len];
        int min = prices[0];
        for(int i=1; i<len; i++){
            maxBefore[i] = Math.max(maxBefore[i-1], prices[i] - min);
            min = Math.min(min, prices[i]);
        }
        int max = prices[len - 1];
        int ret = 0;
        for(int i=len-2; i>=0; i--){
            //Find the biggest price behind.
            max = Math.max(prices[i], max);
            //Profit = Maximum Price - Current Price + First Profit at the Time of Transaction
            //Maximum value
            ret = Math.max(ret, max - prices[i] + maxBefore[i]);
        }
        return ret;
    }

This method takes a long time because it uses two loops, beats 18% of users and uses extra O(n) storage space. Next, we need to improve the algorithm. After discuss ing, we have improved the idea. The basic idea is to use four variables to express the first buy, the first sell, the second buy and the second sell. Then it is updated while traversing. Code in:

public int maxProfit(int[] prices) {
    int len = prices.length;
    if(len <= 1) return 0;
    int a, b, c, d;
    //d denotes the maximum traversing from back to front, c denotes the maximum profit after the first transaction, b denotes the maximum value before the second transaction, and a denotes the sum of profits after the second transaction.
    d = Math.max(prices[len-1], prices[len-2]);
    c = Math.max(prices[len-1] - prices[len-2], 0);
    b = d;
    a = c;
    for(int i=len-3; i>=0; i--) {
        //Here, the meaning of each variable above is combined to understand why each variable is updated in the following formula.
        a = Math.max(b - prices[i], a);
        b = Math.max(prices[i] + c, b);
        c = Math.max(d - prices[i], c);
        d = Math.max(prices[i], d);
    }
    return a;
}

This method can defeat 58% of users, and there is another solution. The idea is the same as above. As shown below, it can defeat 76% of users.

public int maxProfit(int[] prices) {
    // these four variables represent your profit after executing corresponding transaction
    // in the beginning, your profit is 0. 
    // when you buy a stock ,the profit will be deducted of the price of stock.
    int firstBuy = Integer.MIN_VALUE, firstSell = 0;
    int secondBuy = Integer.MIN_VALUE, secondSell = 0;

    for (int curPrice : prices) {
        if (firstBuy < -curPrice) firstBuy = -curPrice; // the max profit after you buy first stock
        if (firstSell < firstBuy + curPrice) firstSell = firstBuy + curPrice; // the max profit after you sell it
        if (secondBuy < firstSell - curPrice) secondBuy = firstSell - curPrice; // the max profit after you buy the second stock
        if (secondSell < secondBuy + curPrice) secondSell = secondBuy + curPrice; // the max profit after you sell the second stock
    }

    return secondSell; // secondSell will be the max profit after passing the prices
}

Posted by laknal on Mon, 11 Feb 2019 18:12:18 -0800