Best Time to Buy and Sell Stock with Transaction Fee

Medium Dynamic Programming State Machine DP - Stock Problems Original on LeetCode

Best Time to Buy and Sell Stock with Transaction Fee is a medium dynamic programming problem solved with the state machine dp - stock problems pattern. The best approach, optimal (two-state machine), runs in O(n) time and O(1) space. Below are 2 approaches in Java, from memoised recursion over (day, holding) up.

Problem

Unlimited transactions again, but each sale costs a transaction fee. Return the maximum profit.

Examples

Example 1

Input
prices = [1, 3, 2, 8, 4, 9], fee = 2
Output
8
Why
Buy 1 sell 8 (+7 - 2), buy 4 sell 9 (+5 - 2).

Example 2

Input
prices = [1, 3, 7, 5, 10, 3], fee = 3
Output
6

Constraints

  • 1 <= prices.length <= 5 * 10^4; 0 <= fee < 5 * 10^4.
  • The fee is paid once per completed transaction.

Animated walkthrough

A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.

Concepts first, then the problem and every approach, step by step.

Space to play or pause · ← → to jump a step · click or drag the bar to seek

Solutions

Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.

ApproachTimeSpace
Memoised recursion over (day, holding)O(n)O(n)
Optimal (two-state machine)O(n)O(1)

1Memoised recursion over (day, holding)

TimeO(n)
SpaceO(n)

At each day, if holding, either sell (price - fee) or wait; if not holding, either buy (-price) or wait.

  1. f(i, holding) with memo; f(n, *) = 0.
Java
class Solution {
    private Integer[][] memo;

    public int maxProfit(int[] prices, int fee) {
        memo = new Integer[prices.length][2];
        return f(prices, fee, 0, 0);
    }

    private int f(int[] p, int fee, int i, int holding) {
        if (i == p.length) return 0;
        if (memo[i][holding] != null) return memo[i][holding];
        int wait = f(p, fee, i + 1, holding);
        int act = holding == 1 ? p[i] - fee + f(p, fee, i + 1, 0) : -p[i] + f(p, fee, i + 1, 1);
        return memo[i][holding] = Math.max(wait, act);
    }
}

2Optimal (two-state machine)

TimeO(n)
SpaceO(1)

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

  1. hold = -prices[0], free = 0; iterate.
Java
class Solution {
    public int maxProfit(int[] prices, int fee) {
        int hold = -prices[0], free = 0;
        for (int i = 1; i < prices.length; i++) {
            int newHold = Math.max(hold, free - prices[i]);
            free = Math.max(free, hold + prices[i] - fee);
            hold = newHold;
        }
        return free;
    }
}

Edge cases to test

  • A fee larger than any rise (answer 0)

Hints

Hint 1

Same two-state machine as Stock II. Subtract the fee when you sell.

FAQ

What is the best time complexity for Best Time to Buy and Sell Stock with Transaction Fee?

Optimal (two-state machine) runs in O(n) time and O(1) extra space.

Which pattern does Best Time to Buy and Sell Stock with Transaction Fee use?

It is a dynamic programming problem that uses the state machine dp - stock problems pattern. Other problems with the same pattern: Best Time to Buy and Sell Stock, Best Time to Buy and Sell Stock II, Best Time to Buy and Sell Stock with Cooldown.

Is there a brute force solution for Best Time to Buy and Sell Stock with Transaction Fee?

Yes. Memoised recursion over (day, holding) takes O(n) time and O(n) space. At each day, if holding, either sell (price - fee) or wait; if not holding, either buy (-price) or wait.

Which edge cases should I test for Best Time to Buy and Sell Stock with Transaction Fee?

A fee larger than any rise (answer 0).