Best Time to Buy and Sell Stock III

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

Best Time to Buy and Sell Stock III is a hard dynamic programming problem solved with the state machine dp - stock problems pattern. The best approach, optimal (four-state machine), runs in O(n) time and O(1) space. Below are 2 approaches in Java, from split into two halves up.

Problem

You may complete at most two transactions (buy then sell, twice), and you must sell before buying again. Return the maximum profit.

Examples

Example 1

Input
prices = [3, 3, 5, 0, 0, 3, 1, 4]
Output
6
Why
Buy 0 sell 3, buy 1 sell 4.

Example 2

Input
prices = [1, 2, 3, 4, 5]
Output
4
Why
One transaction is enough.

Constraints

  • 1 <= prices.length <= 10^5.
  • At most two transactions, not overlapping.

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
Split into two halvesO(n)O(n)
Optimal (four-state machine)O(n)O(1)

1Split into two halves

TimeO(n)
SpaceO(n)

left[i] = best single transaction in prices[0..i]; right[i] = best in prices[i..n-1]. The answer is max over i of left[i] + right[i].

  1. Left pass with the minimum so far; right pass with the maximum so far.
  2. Combine.
Java
class Solution {
    public int maxProfit(int[] prices) {
        int n = prices.length;
        int[] left = new int[n], right = new int[n];
        int min = prices[0];
        for (int i = 1; i < n; i++) {
            min = Math.min(min, prices[i]);
            left[i] = Math.max(left[i - 1], prices[i] - min);
        }
        int max = prices[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            max = Math.max(max, prices[i]);
            right[i] = Math.max(right[i + 1], max - prices[i]);
        }
        int best = 0;
        for (int i = 0; i < n; i++) best = Math.max(best, left[i] + right[i]);
        return best;
    }
}

2Optimal (four-state machine)

TimeO(n)
SpaceO(1)

buy1 = max(buy1, -p); sell1 = max(sell1, buy1 + p); buy2 = max(buy2, sell1 - p); sell2 = max(sell2, buy2 + p). Each state builds on the previous one, and sell2 is the answer.

  1. buy1 = buy2 = -infinity, sell1 = sell2 = 0.
  2. Update all four in order for each price.
Java
class Solution {
    public int maxProfit(int[] prices) {
        int buy1 = Integer.MIN_VALUE, sell1 = 0, buy2 = Integer.MIN_VALUE, sell2 = 0;
        for (int p : prices) {
            buy1 = Math.max(buy1, -p);
            sell1 = Math.max(sell1, buy1 + p);
            buy2 = Math.max(buy2, sell1 - p);
            sell2 = Math.max(sell2, buy2 + p);
        }
        return sell2;
    }
}

Edge cases to test

  • Only one transaction is profitable
  • Falling prices (0)

Hints

Hint 1

Track four states in order: after the first buy, after the first sell, after the second buy, after the second sell.

FAQ

What is the best time complexity for Best Time to Buy and Sell Stock III?

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

Which pattern does Best Time to Buy and Sell Stock III 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 Transaction Fee.

Is there a brute force solution for Best Time to Buy and Sell Stock III?

Yes. Split into two halves takes O(n) time and O(n) space. left[i] = best single transaction in prices[0..i]; right[i] = best in prices[i..n-1].

Which edge cases should I test for Best Time to Buy and Sell Stock III?

Only one transaction is profitable; Falling prices (0).