Browse curriculum

Best Time to Buy and Sell Stock with Transaction Fee

Maximize profit from unlimited trades when every sale costs a fee, with a two-state dynamic program over days: holding a share or holding cash.

Problem Understanding

Best Time to Buy and Sell Stock with Transaction Fee: given daily prices and a fee, make as many transactions as you like, holding at most one share at a time, and paying fee for each one. Return the maximum profit.

Examples: [1,3,2,8,4,9], fee 2 → 8 (buy 1, sell 8; buy 4, sell 9); [1,3,7,5,10,3], fee 3 → 6.

The Intuition: Two Running Bests

This is the state-machine dynamic programming from Stock with Cooldown, with one state fewer:

  1. cash: best profit ending the day without a share. Either stay out, or sell today: hold + price − fee.
  2. hold: best profit ending the day with a share. Either keep it, or buy today: cash − price.
  3. Answer: cash on the last day.

Without a fee this reduces to Best Time to Buy and Sell Stock II, where taking every rise is optimal.

Interactive Walkthrough

FEE 2 PER SALE

DAY 0

day

0

1

2

3

4

5

price

1
3
2
8
4
9

cash

0

hold

-1

day

0

profit

:

 

Day 0, price 1: cash = 0 (do nothing), hold = −1 (buy today). Each sale costs a fee of 2

Next

Day 1, price 3: cash = max(0, sell -1 + 3 − 2 = 0) = 0; hold = max(-1, buy 0 − 3 = -3) = -1

Free preview: the first 3 of 7 steps

prices

fee

Each column is a day; the day being computed is solid and yesterday's states are tinted. At the end the winning path through the states turns green and the buys and sells are labeled. Try Fee wins to see a dip ignored.

Dry Run Table

Input: [1,3,2,8,4,9], fee 2.

Day Price cash hold
0 1 0 −1
1 3 0 −1
2 2 0 −1
3 8 5 −1
4 4 5 1
5 9 8 1

Answer: 8 (buy at 1, sell at 8; buy at 4, sell at 9).

The Solution Template

Two variables updated once per day.

Best Time to Buy and Sell Stock with Transaction Fee Code
1var maxProfit = function(prices, fee) {
2 let cash = 0, hold = -prices[0];
3 for (let i = 1; i < prices.length; i++) {
4 const prevCash = cash;
5 cash = Math.max(cash, hold + prices[i] - fee);
6 hold = Math.max(hold, prevCash - prices[i]);
7 }
8 return cash;
9};

Edge Cases & Common Mistakes

  • One day: no sale possible; the answer is 0.
  • Fee larger than every rise: never trade; cash stays 0.
  • Charging the fee on both buy and sell: that is twice per trade.
  • Greedy on every rise: pays the fee on each small swing; use the DP.
  • Returning max(cash, hold): hold is never larger than cash at the end, but returning cash is the honest answer.

Summary

Keep the best profit holding cash and holding a share; each day either keep the state or switch, paying the fee on each sale. Return cash. O(n) time, O(1) space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Start

    Day 0: cash = 0, hold = -prices[0].

  2. Each day

    cash = max(cash, hold + price - fee); hold = max(hold, previous cash - price).

  3. Answer

    Return cash after the last day: ending with a share never helps.

Frequently asked questions

Why two states?

At the end of any day you either own one share or you do not, and what you may do tomorrow depends only on that. So two numbers per day are enough: the best profit so far if you end the day holding a share (hold), and if you end it with cash only (cash).


Why not just add every price increase, like Stock II?

With a fee, splitting one long rise into several trades pays the fee several times. For [1, 3, 7, 5, 9] and fee 3, one trade from 1 to 9 earns 5, while trading each rise separately earns less. The DP decides automatically whether a dip is deep enough to be worth selling and rebuying.


Does it matter whether the fee is charged on buy or sell?

No, as long as it is charged once per trade. Subtracting it on the buy (hold = cash - price - fee) gives the same answer; charging it on the sell, as here, keeps the day-0 state simple.


Why is updating cash before hold on the same day safe?

In the snippets, hold reads yesterday's cash (prevCash). Even reading today's new cash would be safe: it would mean selling and buying on the same day, which only loses the fee and is never chosen as an improvement.

New to the technique behind this problem? Watch it run step by step:

Dynamic Programming Visualization

Applying for software engineering roles? Free, no sign-up:

AI resume checker: match your resume to the job description