InterviewPrepKit

Home / Coding / 2-D Dynamic Programming

Best Time to Buy and Sell Stock with Cooldown

medium Original ↗
Solving tips
  • Recognize this as a state-machine DP: each day you are in exactly one of three states (holding, sold-today, free/idle), so the second table dimension is the state, not a second sequence.
  • Write the transitions: hold = max(keep holding, buy from free); sold = yesterday's hold + price; free = max(stay free, yesterday's sold) — the sold->free->hold chain is what structurally enforces the one-day cooldown.
  • Target O(n) time and O(1) space with three rolling scalars; snapshot yesterday's sold before overwriting so free reads the correct prior value.
  • Common pitfall: initialize hold to -prices[0] (not 0) and return max(sold, free) at the end, since ending while still holding is never optimal.

Problem

You are given prices, where prices[i] is the price of one share on day i. You may complete as many buy/sell transactions as you like, but with two rules:

  • You may hold at most one share at a time (you must sell before buying again).
  • After you sell, you must wait a full cooldown day before you are allowed to buy again (so the earliest re-buy is two days after a sale).

Return the maximum total profit you can achieve.

Examples

  • [1, 2, 3, 0, 2]3 — buy day 0 (1), sell day 2 (3) for +2, forced cooldown day 3, buy day 3 is blocked so buy… the transaction schedule buy, sell, cooldown, buy, sell over days 0..4 gives (3-1) + (2-0) = 3.
  • [1]0 — a single day gives no chance to sell.
  • [6, 1, 3, 2, 4, 7]6 — just buy at the 1 (day 1) and sell at the 7 (day 5): 7 - 1 = 6; no split schedule beats holding through.

Constraints

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

n up to 5000 makes an exponential “try every buy/sell schedule” search hopeless — the expected solution is O(n) with a constant number of states per day.

Think about it first

Hint 1 On each day you are in exactly one situation: you currently *hold* a share, you *just sold* today (so tomorrow is a forced cooldown), or you are *free* to buy. Track the best profit reachable in each situation as you sweep the days.
Hint 2 Let the day be one axis and the situation (hold / sold-today / free) be the other. That is a 2-D table `dp[day][state]`. Each cell only depends on yesterday's cells — write the transition from day `i-1` to day `i` for all three states.
Hint 3 `hold[i] = max(hold[i-1], free[i-1] - prices[i])`, `sold[i] = hold[i-1] + prices[i]`, `free[i] = max(free[i-1], sold[i-1])`. The cooldown is encoded by the fact that you can only reach `hold` from `free`, and you only reach `free` from `sold` or `free`. The answer is `max(sold[n-1], free[n-1])`.
Your workspace Not runnable by design — this is your interview scratchpad. Saved on this device.