JunyiCode
4/4/2020 - 7:52 PM

123. Best Time to Buy and Sell Stock III

经典,多理解

/*
理解思路和The order of maxProfit2, lowestBuyPrice2, maxProfit1, lowestBuyPrice1
lowestBuyPrice2 = min(p - maxProfit1[high] + maxProfit1[low])
*/


class Solution {
	public static int maxProfit(int [] prices){
	    int maxProfit1 = 0; 
	    int maxProfit2 = 0; 
	    int lowestBuyPrice1 = Integer.MAX_VALUE;
	    int lowestBuyPrice2 = Integer.MAX_VALUE;
	   
	    for(int p:prices){
	    	maxProfit2 = Math.max(maxProfit2, p - lowestBuyPrice2);
            // lowestBuyPrice2 = min(p - maxProfit1[high] + maxProfit1[low])
	    	lowestBuyPrice2 = Math.min(lowestBuyPrice2, p - maxProfit1);
	    	maxProfit1 = Math.max(maxProfit1, p - lowestBuyPrice1);
	    	lowestBuyPrice1 = Math.min(lowestBuyPrice1, p);
	    }
	    return maxProfit2;
    }
}
/*
T[i][j], i = transaction, j = jth day
                T[i][j - 1], not transacting on jth day
              /
T[i][j] = max 
              \
                T[i - 1][m] + (prices[i] - prices[m]), for m = 0,..., j - 1
                best you can get by completing transaction on jth day
*/


class Solution {
    public int maxProfit(int[] prices) {
        return maxProfitSlowSolution(prices, 2);
    }
    
    
    public int maxProfitSlowSolution(int prices[], int K) {
        if (K == 0 || prices.length == 0) {
            return 0;
        }

        int T[][] = new int[K+1][prices.length];

        for (int i = 1; i < T.length; i++) {
            for (int j = 1; j < T[0].length; j++) {
                int maxVal = 0;
                for (int m = 0; m < j; m++) {
                    maxVal = Math.max(maxVal, prices[j] - prices[m] + T[i-1][m]);
                }
                T[i][j] = Math.max(T[i][j-1], maxVal);
            }
        }
        // printActualSolution(T, prices);
        return T[K][prices.length - 1];
    }
    
    
    //use stack to store the order
    public void printActualSolution(int T[][], int prices[]) {
        int i = T.length - 1;
        int j = T[0].length - 1;

        Deque<Integer> stack = new LinkedList<>();
        while(true) {
            if(i == 0 || j == 0) {
                break;
            }
            if (T[i][j] == T[i][j-1]) {
                j = j - 1;
            } else {
                stack.addFirst(j);
                int maxDiff = T[i][j] - prices[j];
                for (int k = j-1; k >= 0; k--) {
                    if (T[i-1][k] - prices[k] == maxDiff) {
                        i = i - 1;
                        j = k;
                        stack.addFirst(j);
                        break;
                    }
                }
            }
        }

        while(!stack.isEmpty()) {
            System.out.println("Buy at price " + prices[stack.pollFirst()]);
            System.out.println("Sell at price " + prices[stack.pollFirst()]);
        }
    }
}