Say you have an array for which the i-th element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most k transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
Example 1:
Input: [2,4,1], k = 2 Output: 2 Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.
Example 2:
Input: [3,2,6,5,0,3], k = 2 Output: 7 Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4. Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
The core challenge of this problem is to maximize the profit from at most k transactions. A transaction consists of buying and then selling one share of the stock. The constraint is that you cannot engage in multiple transactions simultaneously, meaning you must sell the stock before you can buy again.
This problem is significant in financial markets where traders aim to maximize their returns by strategically buying and selling stocks. A common pitfall is to overlook the constraint of non-overlapping transactions, which can lead to incorrect solutions.
To solve this problem, we can use dynamic programming. The idea is to maintain two arrays: one for the maximum profit up to the current day with at most j transactions, and another for the maximum profit up to the previous day with at most j-1 transactions.
We start with a naive solution that considers all possible pairs of buy and sell days, but this approach is not optimal due to its high time complexity. Instead, we use dynamic programming to optimize the solution.
The naive solution involves iterating through all possible pairs of buy and sell days, which results in a time complexity of O(n^2). This is not feasible for large inputs.
We use dynamic programming to reduce the time complexity. The key idea is to use two arrays: dp
and maxDiff
. The dp
array stores the maximum profit up to day i
with at most j
transactions, and the maxDiff
array helps in calculating the maximum difference between the current price and the previous maximum profit.
1. Initialize a 2D array dp
where dp[j][i]
represents the maximum profit up to day i
with at most j
transactions.
2. Iterate through the number of transactions from 1 to k
.
3. For each transaction, iterate through the days from 1 to n
.
4. Use a variable maxDiff
to keep track of the maximum difference between the current price and the previous maximum profit.
5. Update the dp
array based on the maximum profit calculated using maxDiff
.
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
// Function to calculate the maximum profit with at most k transactions
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
if (n == 0) return 0;
// If k is greater than n/2, it's equivalent to unlimited transactions
if (k >= n / 2) {
int maxProfit = 0;
for (int i = 1; i < n; ++i) {
if (prices[i] > prices[i - 1]) {
maxProfit += prices[i] - prices[i - 1];
}
}
return maxProfit;
}
// Initialize dp array
vector<vector<int>> dp(k + 1, vector<int>(n, 0));
for (int j = 1; j <= k; ++j) {
int maxDiff = -prices[0];
for (int i = 1; i < n; ++i) {
dp[j][i] = max(dp[j][i - 1], prices[i] + maxDiff);
maxDiff = max(maxDiff, dp[j - 1][i] - prices[i]);
}
}
return dp[k][n - 1];
}
// Example usage
int main() {
vector<int> prices1 = {2, 4, 1};
int k1 = 2;
cout << "Maximum profit for example 1: " << maxProfit(k1, prices1) << endl;
vector<int> prices2 = {3, 2, 6, 5, 0, 3};
int k2 = 2;
cout << "Maximum profit for example 2: " << maxProfit(k2, prices2) << endl;
return 0;
}
The time complexity of the optimized solution is O(n*k), where n
is the number of days and k
is the number of transactions. The space complexity is also O(n*k) due to the use of the dp
array.
Compared to the naive solution with a time complexity of O(n^2), the optimized solution is significantly more efficient, especially for large inputs.
1. If the number of days n
is 0, the maximum profit is 0.
2. If k
is greater than or equal to n/2
, it is equivalent to unlimited transactions.
3. If the prices array is strictly decreasing, the maximum profit is 0.
To test the solution comprehensively, consider the following test cases:
Use testing frameworks like Google Test for C++ to automate the testing process.
1. Break down the problem into smaller subproblems and solve them using dynamic programming.
2. Understand the constraints and optimize the solution accordingly.
3. Practice solving similar problems to improve problem-solving skills.
In this blog post, we discussed the problem of finding the best time to buy and sell stock with at most k transactions. We explored a naive solution and an optimized solution using dynamic programming. We also analyzed the time and space complexity of the solutions and discussed edge cases and testing strategies.
Understanding and solving such problems is crucial for developing strong problem-solving skills and optimizing algorithms for real-world applications.