Best Time to Buy and Sell Stock III

LeetCode problem 123: Best Time to Buy and Sell Stock III.

## Problem description

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
**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
**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
**Input:** prices = [7,6,4,3,1]
**Output:** 0
**Explanation:** In this case, no transaction is done, i.e. max profit = 0.
Example 4
**Input:** prices = [1]
**Output:** 0
Constraints
* `1 <= prices.length <= 105`
* `0 <= prices[i] <= 105`

## Problem analysis

One approach is to reuse the ideas from the Best Time to Buy and Sell Stock problem. However, since we can have **at most two transactions**, we can decompose the two transactions into four sequential actions:

1. Buying the first stock
2. Selling the first stock
3. Buying the second stock
4. Selling the second stock

We define the following variables:

1. `balance1` – the maximal balance we can have after completing the first purchase. Initialize it to `INT_MIN`.
2. `profit1` – the maximal profit after selling the first stock, or after not making any transactions if it does not yield greater profit. Initialize it to 0.
3. `balance2` – the maximal balance we can have after completing the second purchase. Initialize it to `INT_MIN`.
4. `profit2` – the maximal profit after selling at most two stocks. Initialize it to 0.

We will loop through the input array day-wise, and update these variables as follows:

1. Update `balance1`: `balance1 = std::max(balance1, -prices[i])`. This means that we want to make the first purchasing price as low as possible.
2. Update `profit1`: `profit1 = std::max(profit1, balance1 + prices[i])`. This means that for each day *i*, we want to pick the option (to sell or not to sell) that yields the greater profit.
3. Update `balance2`: `balance2 = std::max(balance2, profit1 - prices[i])`. In the `std::max` function:
	* `balance2` means we do not make the second purchase on day *i*.
	* `profit1 - prices[i]` means we make the second purchase on day *i*. (If `profit1 == 0`, this is equivalent to making the first purchase on day *i*.)
4. Update `profit2`: `profit2 = std::max(profit2, balance2 + prices[i])`. In the `std::max` function:
	* `profit2` means we do not sell our second stock on day *i*.
	* `balance2 + prices[i]` means we do sell our second stock on day *i*. (If `profit1 == 0`, this is equivalent to selling the first stock on day *i*.)

Loop until we have covered all the days. Then `profit2` will be the final result of the problem.

### Working example

* Input: 7, 2, 1, 9, 6, 10, 3, 2, 5, 14, 10

* Return: **21**
	1. Buy on day 2 → sell on day 5 (profit: 9)
	2. Buy on day 7 → sell on day 9 (profit: 12)

### Complexity analysis

Time complexity
Since we loop through each day once, and compute the variables `balance1`, `maxProfit1`, `balance2`, and `maxProfit2` in constant time, the total time complexity is **O(n)**, where *n* is the number of days.
Space complexity
Since we did not create additional data structures, the space complexity is **O(1)**.
## Solution

### C++ solution

```
class Solution {
public:
 int maxProfit(std::vector<int>& prices) {
 const int days = prices.size();
 if (days < 2) {
 return 0;
 }

 int balance1 = INT\_MIN, balance2 = INT\_MIN;
 int profit1 = 0, profit2 = 0;
 for (const int& price: prices) {
 balance1 = std::max(balance1, -price);
 profit1 = std::max(profit1, balance1 + price);

 balance2 = std::max(balance2, profit1 - price);
 profit2 = std::max(profit2, balance2 + price);
 }

 return profit2;
 }
};

```

### Java solution

```
class Solution {
 public int maxProfit(int[] prices) {
 final int days = prices.length;
 if (days < 2) {
 return 0;
 }

 int balance1 = Integer.MIN\_VALUE, balance2 = Integer.MIN\_VALUE;
 int profit1 = 0, profit2 = 0;
 for (int price: prices) {
 balance1 = Math.max(balance1, -price);
 profit1 = Math.max(profit1, balance1 + price);

 balance2 = Math.max(balance2, profit1 - price);
 profit2 = Math.max(profit2, balance2 + price);
 }

 return profit2;
 }
}

```

## See also

Best time to buy and sell stock
 122
 123
 188
 309
 714