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 stock transactions given the constraint that you can only hold one stock at a time and you can complete at most k transactions. This problem is significant in financial markets where traders aim to maximize their returns by buying and selling stocks at optimal times.
Common pitfalls include misunderstanding the constraint of not holding multiple stocks simultaneously and not considering the optimal number of transactions.
To solve this problem, we can use dynamic programming. The idea is to maintain a table where the entry at index (i, j)
represents the maximum profit achievable using at most i
transactions up to day j
.
We can start with a naive solution that tries all possible pairs of buy and sell days, but this would be inefficient with a time complexity of O(n^2)
. Instead, we can optimize this using dynamic programming.
We use a 2D DP array where dp[i][j]
represents the maximum profit using at most i
transactions up to day j
. The state transition can be derived as follows:
j
, we can either not trade, in which case dp[i][j] = dp[i][j-1]
, or we can sell the stock on day j
. To find the best day to buy the stock, we need to consider all previous days m
and calculate the profit as prices[j] - prices[m] + dp[i-1][m]
.To optimize this, we can keep track of the maximum value of dp[i-1][m] - prices[m]
as we iterate through the days.
Here is a step-by-step breakdown of the algorithm:
dp
with dimensions (k+1) x n
, where n
is the number of days.k
.n-1
.dp[i-1][m] - prices[m]
as max_diff
.dp[i][j]
as the maximum of dp[i][j-1]
and prices[j] + max_diff
.def maxProfit(k, prices):
# If there are no prices or k is 0, return 0 profit
if not prices or k == 0:
return 0
n = len(prices)
# If k is greater than n//2, it's equivalent to unlimited transactions
if k >= n // 2:
return sum(max(prices[i] - prices[i - 1], 0) for i in range(1, n))
# Initialize the DP table
dp = [[0] * n for _ in range(k + 1)]
# Fill the DP table
for i in range(1, k + 1):
max_diff = -prices[0]
for j in range(1, n):
dp[i][j] = max(dp[i][j - 1], prices[j] + max_diff)
max_diff = max(max_diff, dp[i - 1][j] - prices[j])
return dp[k][-1]
# Example usage
print(maxProfit(2, [2, 4, 1])) # Output: 2
print(maxProfit(2, [3, 2, 6, 5, 0, 3])) # Output: 7
The time complexity of this solution is O(k * n)
, where k
is the number of transactions and n
is the number of days. The space complexity is also O(k * n)
due to the DP table.
This is a significant improvement over the naive O(n^2)
approach.
Consider the following edge cases:
k = 0
: No transactions allowed, so the output should be 0.k >= n // 2
: This is equivalent to unlimited transactions, and we can use a simpler greedy approach.To test the solution comprehensively, consider the following test cases:
Using a testing framework like unittest
in Python can help automate and manage these tests.
When approaching such problems, it's essential to:
In this blog post, we discussed the problem of finding the maximum profit from stock transactions with at most k
transactions. We explored a dynamic programming approach to solve the problem efficiently and analyzed its complexity. Understanding and solving such problems is crucial for developing strong algorithmic skills.
For further reading and practice, consider the following resources: