# 123_Best_Time_to_Buy_and_Sell_Stock_III ###### tags: `leetcode` ## Problem Statement 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: 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 <= 10^5^ > 0 <= prices[i] <= 10^5^ ## Solution - There is one more chance for transaction, after the normal procedure of looking for 1 transaction, there are 4 possibilities for adding 1 more transaction. 1. Add 1 before the current one. 2. Add 1 adter the current one. 3. Split the current one into 2 transactions. 4. Remain the same. - As the result, when selecting the first transaction, store the begin and the end of the index. ```cpp= // max_: the count of the gain // temp: the lower bound candidate // c: control of whether to write new lower bound // change the lower and upper bound index when max_ is changed for (int i= 1; i< prices.size(); i++) { if (l+ prices[i]- prices[i- 1]> 0) { l+= prices[i]- prices[i- 1]; if (c) { temp= i; c= 0; } } else { l= 0; c= 1; } if (max_< l) { max_= l; p2= i+ 1; p1= temp; } } ``` - To compare whether adding one more transaction, the prerequisite is that there is transaction and the number of index need to be bigger than 1 ```cpp= if (p2!= 0&& prices.size()> 1) ``` - The 3 possibilities is considered: 1. Add one before transaction: count one transaction from the beginning till the lower bound. ```cpp= for (int i= 1; i< p1; i++) { l= max(l+ prices[i]- prices[i- 1], 0); max_l= max(max_l, l); } ``` 2. Add one after transaction: count one transaction from the upper bound till the end. ```cpp= for (int i= p2; i< prices.size(); i++) { l= max(l+ prices[i]- prices[i- 1], 0); max_r= max(max_r, l); } ``` 3. Split can be seperated into 2 cases: - Split from the smallest one among the middle - Split from the biggest one among the middle Since the ```min_element()``` and ```max_element()``` gives the first smallest element without scanning all the index of the smallest element, the ```while``` loop is required. ```cpp= vector<int>::iterator a, b; b= min_element(prices.begin()+ p1, prices.begin()+ p2- 1); do { a= max_element(prices.begin()+ p1, b); temp= (*a> *b)? prices[p2- 1]- *b+ *a- prices[p1- 1]: 0; max_m= max(max_m, temp); b= find(b+ 1, prices.begin()+ p2- 1, *b); }while (b!= prices.begin()+ p2- 1); ``` ```cpp= b= max_element(prices.begin()+ p1, prices.begin()+ p2- 1); do { a= min_element(b, prices.begin()+ p2- 1); temp= (*a< *b)? prices[p2- 1]- *a+ *b- prices[p1- 1]: 0; max_m= max(max_m, temp); b= find(b+ 1, prices.begin()+ p2- 1, *b); }while (b!= prices.begin()+ p2- 1); ``` - After all the possibilities, compare the result. ```cpp= max_l= max(max_l, max_r); max_= max(max_, max_+ max_l); return max(max_, max_m); ```