AlgoMaster Logo

Reconstruct Itinerary

Last Updated: March 28, 2026

hard
3 min read

Understanding the Problem

This problem is really about finding an Eulerian path in a directed graph. Each ticket is a directed edge from one airport to another, and we need to traverse every edge exactly once, starting from "JFK." The twist is the lexicographic ordering requirement: when multiple valid paths exist, we need the one that's smallest when read as a string.

The key observation is that this isn't a standard DFS where we just visit nodes. We need to visit every edge exactly once. That distinction matters because we might visit the same airport multiple times (as in Example 2, where JFK, ATL, and SFO are all visited twice). This is exactly the setup for Hierholzer's algorithm, which finds Eulerian paths in graphs.

Key Constraints:

  • 1 <= tickets.length <= 300 → With at most 300 edges, even O(n^2) approaches are fine. But the graph structure suggests DFS-based solutions are natural.
  • from_i.length == 3, to_i.length == 3 → Airport codes are always 3 uppercase letters, so string comparisons are constant time.
  • "All tickets form at least one valid itinerary" → We're guaranteed an Eulerian path exists. No need to check for existence.
  • "Must use all tickets exactly once" → This is the Eulerian path condition: traverse every edge exactly once.

Approach 1: DFS with Backtracking

Intuition

The most direct way to think about this: build a graph from the tickets, sort each airport's destinations lexicographically, and then do a DFS from "JFK," trying to use all tickets. If we hit a dead end before using all tickets, we backtrack and try the next destination.

This approach is correct because sorting guarantees we try the lexicographically smallest path first. The first complete path we find (one that uses all tickets) is our answer, so we can stop immediately.

Algorithm

  1. Build an adjacency list from the tickets. For each departure airport, store a sorted list of destination airports.
  2. Track which tickets have been used (since the same route can appear multiple times, we track ticket usage, not just edge existence).
  3. Start DFS from "JFK." At each airport, try destinations in sorted order.
  4. For each destination, mark the ticket as used and recurse. If the recursion uses all tickets, we've found our answer.
  5. If not, unmark the ticket (backtrack) and try the next destination.

Example Walkthrough

1Start at JFK. Sorted neighbors: JFK->[ATL,SFO], ATL->[JFK,SFO], SFO->[ATL]
0
JFK
1/6

Code

This approach works correctly but can be slow due to backtracking. What if there was a way to build the path in a single traversal, without ever needing to undo work?

Approach 2: Hierholzer's Algorithm (Optimal)

Intuition

Hierholzer's algorithm is the elegant solution to Eulerian path problems. The idea is beautifully simple: do a DFS, always visiting the lexicographically smallest unused neighbor. When you reach a dead end (a node with no more outgoing edges), add that node to the front of the result and backtrack.

Why does building the path in reverse work? Consider what happens at a dead end. If we're stuck at some airport with no more tickets, it means all edges leading out of that airport have been used. In an Eulerian path, the last node in the path must be a dead end. By adding dead-end nodes to the front, we're effectively placing the "tail" of our path first, then filling in the rest as we backtrack.

Algorithm

  1. Build an adjacency list where each airport maps to a min-heap (priority queue) of its destinations.
  2. Start DFS from "JFK."
  3. At each airport, while there are unused outgoing tickets, pop the smallest destination and recurse.
  4. When no more outgoing tickets remain (dead end), add the current airport to the front of the result.
  5. The final result is the Eulerian path in the correct order.

Example Walkthrough

1DFS from JFK. Heap: JFK->[ATL,SFO], ATL->[JFK,SFO], SFO->[ATL]. Result: []
1/7

Code