LeetCode #332 Hard

Reconstruct Itinerary

Use every airline ticket once to build the lexicographically smallest itinerary starting at JFK.

grapheulerian-pathdfs
Open on LeetCode ↗
02

Intuition

Greedily taking the smallest destination can enter a dead end before all tickets are used. The tickets are directed edges and the requested route uses every edge exactly once, so this is an Eulerian-path problem. Hierholzer's algorithm safely follows edges until stuck and records airports while backtracking. Choosing outgoing edges in lexical order produces the smallest valid itinerary.

How to spot this pattern

The phrase 'use every ticket/edge exactly once' signals an Eulerian trail rather than ordinary path search. When lexical minimality is also required, order each vertex's outgoing edges while running Hierholzer's algorithm.

03

Approach

1

Store destinations as lexical min-heaps

For every ticket from -> to, push to into the heap for from. Tickets remain separate heap entries, so duplicate flights are preserved.

2

Consume an entire trail before recording its airport

DFS from JFK, repeatedly removing the smallest available outgoing ticket and recursing into its destination. Append the current airport only after it has no tickets left, which places dead ends at the correct suffix.

3

Reverse the postorder route

Postorder records the Eulerian path from end to start. Reverse it once to obtain the itinerary, with all tickets used exactly once and lexical choices resolved at each departure.

04

Solution

1class Solution:
2 def findItinerary(self, tickets: List[List[str]]) -> List[str]:
3 graph = defaultdict(list)
4 for source, destination in tickets:
5 heappush(graph[source], destination)
6 
7 route = []
8 def visit(airport):
9 while graph[airport]:
10 visit(heappop(graph[airport]))
11 route.append(airport)
12 
13 visit('JFK')
14 return route[::-1]
05

Common pitfalls

Appending before exploring

✗ Wrong
route.append(airport)
visit(next_airport)
✓ Right
visit(next_airport)
route.append(airport)

Eulerian construction records vertices on backtracking so premature dead ends land at the end.

Using a set for destinations

✗ Wrong
graph[source].add(destination)
✓ Right
heappush(graph[source], destination)

A set destroys duplicate tickets, even though each duplicate must be consumed.

Returning postorder directly

✗ Wrong
return route
✓ Right
return route[::-1]

Airports are appended from the route's end back toward JFK.

06

Edge cases

Duplicate identical tickets

Each heap insertion is a separate edge and is popped exactly once.

The smallest immediate destination is a dead end

Postorder insertion delays that dead end instead of invalidating the remaining tour.

A single ticket from JFK

DFS appends the destination then JFK, and reversal returns both airports.

07

Complexity

Time
O(E log E)
Space
O(E)
Every ticket is inserted into and removed from one heap, then stored in the route.