{x}
blog image

Best Time to Buy and Sell Stock IV

You are given an integer array prices where prices[i] is the price of a given stock on the ith day, and an integer k.

Find the maximum profit you can achieve. You may complete at most k transactions: i.e. you may buy at most k times and sell at most k times.

Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).

 

Example 1:

Input: k = 2, prices = [2,4,1]
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.

Example 2:

Input: k = 2, prices = [3,2,6,5,0,3]
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.

 

Constraints:

  • 1 <= k <= 100
  • 1 <= prices.length <= 1000
  • 0 <= prices[i] <= 1000

Solution Explanation for Best Time to Buy and Sell Stock IV

This problem asks to find the maximum profit achievable by completing at most k transactions on a given array of stock prices. We cannot engage in multiple transactions simultaneously (must sell before buying again).

Several approaches can solve this problem. Here, we'll focus on the most efficient one: Dynamic Programming.

Dynamic Programming Approach

The core idea is to build a DP table to store the maximum profit achievable at each state. We define dp[i][j] as the maximum profit achievable after considering the first i days and completing at most j transactions.

The state transition equation is derived by considering two possibilities at each day i:

  1. Not trading: The maximum profit remains the same as the previous day, dp[i][j] = dp[i-1][j].
  2. Trading: This involves a buy and sell operation. To find the maximum profit from a trade on day i, we need to find the maximum profit from previous days, where at most j-1 transactions were completed before buying on day i. We then add the profit gained by selling on day i. This is represented as dp[i][j] = max(dp[i][j], dp[m][j-1] + prices[i] - prices[m]), where m iterates through the days before i.

Optimization: The naive implementation of the above would lead to O(n^2 * k) time complexity. However, we can optimize it to O(n*k) by noticing that we don't need to iterate through all m for each day i. Instead, we only need the maximum value dp[m][j-1] - prices[m] calculated so far. We can store this maximum value in a variable and update it at each iteration.

Base Cases:

  • dp[i][0] = 0 for all i: No transactions allowed, so no profit.
  • dp[0][j] = 0 for all j: No days considered, so no profit.

Code Implementation (Python):

def maxProfit(k: int, prices: List[int]) -> int:
    n = len(prices)
    if n == 0 or k == 0:  # Handle edge cases
        return 0
 
    dp = [[0] * (k + 1) for _ in range(n + 1)]  # DP table initialization
 
    for i in range(1, n + 1):
        for j in range(1, k + 1):
            max_so_far = 0
            for m in range(i):
                max_so_far = max(max_so_far, dp[m][j - 1] - prices[m])
            dp[i][j] = max(dp[i - 1][j], max_so_far + prices[i - 1])
 
    return dp[n][k]  # Maximum profit after considering all days and transactions
 

Time Complexity: O(nk) - Due to nested loops iterating through days and transactions. Space Complexity: O(nk) - To store the DP table. This can be further optimized to O(k) by using only two rows of the DP table to store the previous and current states.

Code Implementation (with O(k) Space Optimization - Python):

def maxProfit(k: int, prices: List[int]) -> int:
    n = len(prices)
    if n == 0 or k == 0:
        return 0
    dp = [[0] * 2 for _ in range(k + 1)]
    for i in range(1, n):
        for j in range(k, 0, -1):
            dp[j][1] = max(dp[j][1], dp[j - 1][0] - prices[i-1])
            dp[j][0] = max(dp[j][0], dp[j][1] + prices[i])
    return dp[k][0]
 

This optimized version maintains only two rows for the DP table, significantly reducing the space complexity. The time complexity remains O(n*k). The other languages would follow a similar structure with slight syntax differences.