MediumDynamic Programming

Best Time to Buy and Sell Stock with Transaction Fee โ€” Solution

Problem

You have a list of daily stock prices and must pay a fixed fee each time you complete a sale. You can buy and sell as many times as you want โ€” but you can only hold one share at a time โ€” and you want to maximize total profit after fees.

  • Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
  • Output: 8
  • Explanation: Buy at 1 and sell at 8 (profit 8 โˆ’ 1 โˆ’ 2 = 5), then buy at 4 and sell at 9 (profit 9 โˆ’ 4 โˆ’ 2 = 3).

Intuition

On any given day you're in exactly one of two states: holding a share or not. The fee discourages selling for small gains, so the decision isn't "sell whenever price goes up" โ€” you need to clear the fee threshold. Tracking just these two states and their best possible profit lets you scan the prices once and make the right choice at every step.

Solution โ€” DP State Machine

Maintain two values through the price list: cash (best profit when you're not holding a share) and held (best profit when you are holding one). Each day, update both by considering whether to act or do nothing.

  1. Initialize cash = 0 (no share, no profit yet) and held = -prices[0] (bought on day 0).
  2. For each subsequent price, compute a temporary copy of the old cash before overwriting it.
  3. Update cash: either stay out of the market, or sell today (held + price โˆ’ fee).
  4. Update held: either keep holding, or buy today using the old cash (prev_cash โˆ’ price).
  5. Return cash โ€” you never want to end while holding a share.
1def maxProfit(prices, fee):
2    cash = 0               # best profit while not holding a share
3    held = -prices[0]      # best profit while holding a share (bought day 0)
4
5    for price in prices[1:]:
6        prev_cash = cash
7        cash = max(cash, held + price - fee)   # sell today or stay out
8        held = max(held, prev_cash - price)    # buy today or keep holding
9
10    return cash

Time: O(n) โ€” one pass through the prices array.
Space: O(1) โ€” only two integer variables regardless of input size.

Complexity Summary

ApproachTimeSpaceWhen to use
DP State MachineO(n)O(1)Unlimited transactions with a per-sale fee

Common Mistakes

  • Not saving the old cash before updating it โ€” if you compute the new cash and immediately use it to compute held, you allow buying and selling on the same day (which this problem prohibits). Save prev_cash first.
  • Charging the fee on both buy and sell โ€” the fee is one flat cost per completed transaction; applying it twice doubles the penalty and produces the wrong answer.
  • Using the no-fee greedy ("collect every upward slope") โ€” without a fee that strategy is correct, but the fee changes the break-even point; small profitable moves become net losses once the fee is applied.
  • Initializing held = 0 instead of held = -prices[0] โ€” buying always costs money; starting held at 0 pretends the first purchase was free, which inflates every subsequent profit calculation.
  • Trying to enumerate buy/sell day pairs explicitly โ€” the number of valid pairs is exponential; the state machine collapses that to a single linear scan by encoding all possible histories into two values.

Related Problems

Ready to practice? Try it on SkillFlow

Adaptive problems, AI follow-up interviews, and a skill score that shows exactly where you need to improve.

Practice This Problem โ†’