Skip to content
DSAPrep

    ↑↓ to move · Enter to open · Esc to close

    Medium2-D DP

    Best Time to Buy And Sell Stock With Cooldown

    You are given an array prices where prices[i] is the price of a given stock on the i-th day.

    Find the maximum profit you can achieve. You may complete as many transactions as you like (buy one and sell one share of the stock multiple times) with the following restriction: after you sell your stock, you cannot buy stock on the next day (cooldown one day).

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

    Example 1

    Input: prices = [1,2,3,0,2]

    Output: 3

    Explanation: transactions = [buy, sell, cooldown, buy, sell]

    Example 2

    Input: prices = [1]

    Output: 0

    Constraints

    • 1 <= prices.length <= 5000
    • 0 <= prices[i] <= 1000
    View original on LeetCode ↗

    On any given day you are in exactly one of three states: holding a share, just sold a share today (so tomorrow is a forced cooldown), or resting (not holding, free to buy). Each day’s best profit for a state only depends on yesterday’s states, which is what makes this a DP problem even though there is no explicit 2-D grid in the final solution — the “two dimensions” are day and state.

    Brute Force Recursion

    Time O(2^n)Space O(n)

    At every day, if you are not holding a stock you can either buy or do nothing; if you are holding, you can either sell (which forces a cooldown the next day) or do nothing. Try every branch and take the best.

    class Solution:
    def maxProfit(self, prices: list[int]) -> int:
    n = len(prices)
    def rec(i: int, holding: bool) -> int:
    if i >= n:
    return 0
    skip = rec(i + 1, holding)
    if holding:
    sell = prices[i] + rec(i + 2, False)
    return max(skip, sell)
    buy = -prices[i] + rec(i + 1, True)
    return max(skip, buy)
    return rec(0, False)

    Two choices per day, and the same (day, holding) pair recurs constantly across different decision paths — exponential blow-up.

    State Machine DP (Bottom-Up)

    OptimalTime O(n)Space O(1)

    Track the best possible profit for each of the three states after processing day i:

    • hold: currently holding a share.
    • sold: sold a share today (tomorrow must be a cooldown).
    • rest: not holding, and free to buy today.

    Transitions, using yesterday’s values:

    • hold = max(hold, rest - prices[i]) — keep holding, or buy today from a resting state.
    • sold = hold + prices[i] — sell the share you were holding.
    • rest = max(rest, sold) — keep resting, or a cooldown day has passed since the last sale.
    class Solution:
    def maxProfit(self, prices: list[int]) -> int:
    if not prices:
    return 0
    hold, sold, rest = -prices[0], 0, 0
    for price in prices[1:]:
    prev_hold, prev_sold, prev_rest = hold, sold, rest
    hold = max(prev_hold, prev_rest - price)
    sold = prev_hold + price
    rest = max(prev_rest, prev_sold)
    return max(sold, rest)

    Watch the three state values update in place on prices = [1, 2, 3, 0, 2]: sold is never spendable the very next day — it only reaches hold through rest, which is exactly the forced cooldown.

    Prices

    d0 1d1 2d2 3d3 0d4 2
    holdown a share
    max(h, r - p)
    -1
    -1
    soldsold today
    h + p
    0
    0
    restfree to buy
    max(r, s)
    0
    0
    answer = max(sold, rest)—
    1 / 6
    currentresult

    Seed day 0 by buying: hold = -price = -1. sold and rest start at 0 because no share has been sold or rested yet.

    Complexity: one pass over n days with O(1) work per day → O(n) time. Only three running values are kept → O(1) space.

    More 2-D DP practice