LeetCode 123. Best Time to Buy and Sell Stock III

Question

You are given an array prices where prices[i] is the price of a given stock on the ith day.

Find the maximum profit you can achieve. You may complete at most two transactions.

Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).

Example 1:

1
2
3
4
Input: prices = [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:

1
2
3
4
Input: prices = [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:

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

Constraints:

  • 1 <= prices.length <= 105
  • 0 <= prices[i] <= 105

Source: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/

Solution

leftProfits[i] means the max profit of all transactions in prices[:i] (they can sell on day i or earlier). Similar for rightProfits[i].

The overlap point of day i for leftProfits[i] and rightProfits[i] is necessary. Because the question requires a result with at most two transactions. The overlap point can help two transactions to be merged into one.

We find seen min price and max price from two different ends to fill two cache arrays.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public int maxProfit(int[] prices) {
if (prices == null || prices.length <= 1) {
return 0;
}
int len = prices.length;
// leftProfits[i] is the max profit of the first transaction in prices[:i] (inclusive)
// rightProfits[i] is the max profit of the second transaction in prices[i:] (inclusive)
// when two transactions overlap on i, they can be merged into one
int[] leftProfits = new int[len];
int[] rightProfits = new int[len];
int leftMin = prices[0];
int rightMax = prices[len - 1];
// k is the distance to the end, to merge two loops into one
for (int k = 1; k < len; k++) {
int l = k, r = len - 1 - k;
leftMin = Math.min(leftMin, prices[l]);
rightMax = Math.max(rightMax, prices[r]);
leftProfits[l] = Math.max(leftProfits[l - 1], prices[l] - leftMin);
rightProfits[r] = Math.max(rightProfits[r + 1], rightMax - prices[r]);
}
int maxProfit = 0;
for (int i = 0; i < len; i++) {
maxProfit = Math.max(maxProfit, leftProfits[i] + rightProfits[i]);
}
return maxProfit;
}
Author

Weihao Ye

Posted on

2022-01-18

Updated on

2022-01-24

Licensed under