In previous dynamic programming problems, we are only evaluating a part of the array starting from the beginnig and iteratively increasing the size of that part. But, what if we are required to evaluate the entire array from the start and somehow derive a value from it? What if we have to divide the entire array into parts and then calculate the sum? Let's have a look at today's problem.
LeetCode 123. Best Time to Buy and Sell Stock III
You are given an array
prices
whereprices[i]
is the price of a given stock on theith
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).
Unlike its preceding questions, this time we are allowed to do at most two transactions. From knowledge of previous question, I only know how to continuosuly increase the size of the subarray and derive value from it. Then it got me thinking, is it possible for me to apply it here?
At first, all seems dull. We must find insight from the entire array because we have to find the two most valuable transactions. Our previous method can only support one transaction. But then, an idea struck me. Since we are allowed two transactions, there must be a middle point that divides the entire array into two, and then we would find the maximum profit from the two halves, allowing us to reuse the same method as in previous questions.
My approach to this is to create another dp array, in addition to the "traditional" one that starts from the beginnig, that, on the contrary, starts at the back. It will then iteratively increase its size at the front at find the maximium gain. The two arrays would then find the maximum profit starting at the two boundaries. Next, we will loop through all the middle points to find the sum of the two transactions, i.e. maximizing the sum of gains starting from left up to k and from k to the back, where k is the middle point. Since we are allowed to buy and sell stocks on the same day, using the same k for the two dp arrays would be acceptable. If there were only one or no continuous increasing trend, we will simply get a 0.
class Solution {
public:
int maxProfit(vector<int>& prices) {
int dpl[prices.size() + 2]; // from start
int dpr[prices.size() + 2]; // from back
memset(dpl, 0, sizeof(dpl));
memset(dpr, 0, sizeof(dpr));
// keep track of the min and max in the two intervals
int leftmin = prices[0], rightmax = prices[prices.size() - 1];
// loop through index
for(int i = 1 ; i <= prices.size(); i++){
// update the two dp arrays in opposite directions
dpl[i] = max(dpl[i-1], prices[i - 1] - leftmin);
dpr[prices.size() + 1 - i] =
max(dpr[i+1], rightmax - prices[prices.size() - i]);
// update the min and max
leftmin = min(leftmin, prices[i-1]);
rightmax = max(rightmax, prices[prices.size() - i]);
}
// stores the max profit
int result = 0;
// loop through the middle points
for(int i = 1; i <= prices.size(); i++){
result = max(result, dpl[i] + dpr[i]);
}
return result;
}
};