This problem is 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." When multiple valid paths exist, we return the one that is smallest when read as a single string.
This is not a standard DFS over nodes. We need to traverse every edge exactly once, which means we may visit the same airport multiple times. In Example 2, JFK, ATL, and SFO are each visited twice. Traversing every edge exactly once is the defining condition of an Eulerian path, and Hierholzer's algorithm is the standard method for constructing one.
1 <= tickets.length <= 300 → With at most 300 edges, an O(E log E) traversal is well within limits, and a backtracking solution that explores a few dead ends still runs fast.from_i.length == 3, to_i.length == 3 → Airport codes are always 3 uppercase letters, so string comparisons take constant time.Build a graph from the tickets, sort each airport's destinations lexicographically, then do a DFS from "JFK," trying to use all tickets. If a branch reaches a dead end before all tickets are used, backtrack and try the next destination at the most recent choice point.
Sorting the destinations means that at every airport we attempt the lexicographically smallest option first. The first complete path we find (one that uses all tickets) is therefore the smallest valid itinerary, so we can return as soon as we find it.
Backtracking can revisit many partial paths before finding the answer. The next approach builds the itinerary in a single traversal, with no undoing.
Hierholzer's algorithm constructs an Eulerian path without backtracking. Do a DFS, always visiting the lexicographically smallest unused neighbor. When an airport has no more outgoing tickets, add it to the front of the result and return to its caller.
Building the path in reverse works because of what a dead end represents. When the DFS gets stuck at an airport with no remaining tickets, every edge out of that airport has already been consumed, so that airport must come last among all the nodes still on the current call stack. Adding dead ends to the front places the tail of the path first, and the rest of the path fills in ahead of it as each recursive call returns.
Pre-order insertion (recording each airport when first visited) breaks on graphs where the greedy smallest choice leads into a branch that returns to the start before other edges are covered. The visit order would then list airports that cannot connect into one path. Post-order insertion avoids this: a node is recorded only once all of its outgoing edges are spent, so the recorded order, reversed, is always a single valid Eulerian path.
Lexicographic minimality comes from the min-heap. At each airport the smallest available destination is taken first, so among all valid Eulerian paths the one produced is the smallest.