1. 程式人生 > 實用技巧 >0123. Best Time to Buy and Sell Stock III (H)

0123. Best Time to Buy and Sell Stock III (H)

Best Time to Buy and Sell Stock III (H)

題目

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 (i.e., you must sell the stock before you buy again).

Example 1:

Input: [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
             Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.

Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.

Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

題意

在一個時刻買入股票,在另一個時刻賣出股票,最多可進行2次交易,求能得到的最大收益。

思路

和 0121 很像,只是限定了最多兩次交易。可以在0121的基礎上進行改進:將陣列分成左右兩個子陣列A(1 -> k)和B(k+1 -> n),分別找到最大收益並相加,改變k找到最大的和就是答案。但這樣做有一個問題,即沒有考慮A中買入B中賣出的情況。繼續改進,我們給A中的最大收益加上一個限制,即必須在第k天賣出,這樣第二次交易就能完全落在B中。


程式碼實現

Java

class Solution {
    public int maxProfit(int[] prices) {
        if (prices.length == 0) {
            return 0;
        }

        int profit = 0;
        int minLeft = prices[0];
        int maxRight = prices[prices.length - 1];
        int[] pRightMax = new int[prices.length];

        // 找到從i開始的右區間能得到的最大收益
        for (int i = prices.length - 2; i >= 0; i--) {
            pRightMax[i] = Math.max(pRightMax[i + 1], maxRight - prices[i]);
            maxRight = Math.max(maxRight, prices[i]);
        }

        for (int i = 1; i < prices.length; i++) {
            // prices[i]-minLeft 為左區間在第i天賣出能得到的最大收益
            if (prices[i] - minLeft >= 0) {
                profit = Math.max(profit, prices[i] - minLeft + (i == prices.length - 1 ? 0 : pRightMax[i + 1]));
            }
            minLeft = Math.min(minLeft, prices[i]);
        }

        return profit;
    }
}