◀ THE GRIND — ADVANCED GRAPHS

Reconstruct Itinerary

The drill: Rebuild a single trip from JFK that uses every ticket in the pile exactly once. When more than one full itinerary is possible, the one that reads smallest airport-code-first wins.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A pile of one-way airline tickets arrives, each naming a departure airport and an arrival airport. Every one of those tickets has to be used exactly once, the trip has to start at JFK, and it has to use up the entire pile.

More than one itinerary can satisfy that — the tie gets broken by reading order: whichever valid full itinerary comes first alphabetically, city code by city code, is the one to hand back.

This input always admits at least one itinerary that uses every ticket, so the only work is finding the lexicographically smallest one, not proving one exists.

EX 01
tickets = [["JFK", "AAA"], ["AAA", "BBB"], ["BBB", "CCC"]]
["JFK", "AAA", "BBB", "CCC"]
STRAIGHT CHAIN, NO BRANCHING
EX 02
tickets = [["JFK", "ABC"], ["JFK", "DEF"], ["DEF", "JFK"]]
["JFK", "DEF", "JFK", "ABC"]
GREEDY JFK->ABC IS A DEAD END; MUST DETOUR THROUGH DEF FIRST
EX 03
tickets = [["JFK", "AAA"], ["AAA", "JFK"], ["JFK", "AAA"]]
["JFK", "AAA", "JFK", "AAA"]
DUPLICATE TICKET USED TWICE
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

This is a path that must consume every edge of a graph exactly once — not a shortest path, and not a search for any valid order, but the one specific order that sorts first.

HINT 2 THE STRUCTURE

Greedily taking the alphabetically smallest next city can strand you at a dead end with unused tickets still in hand. What lets a route recover from a wrong early choice?

HINT 3 ONE STEP FROM THE ANSWER

Hierholzer's trick: recurse into the smallest unused destination first, and only append a city to the itinerary once it has no departures left. That post-order, reversed, is the answer — dead ends naturally settle to the end.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE DETOUR THAT WORKSPATTERN · HIERHOLZER'S ALGORITHMtickets: JFK→ABC, JFK→DEF, DEF→JFK
STACK
— empty —
STEP 1

Sort each city's destinations so the smallest lexical option is tried first. Hierholzer's DFS starts at JFK.

STEP 1 / 8 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/reconstruct-itinerary.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        graph = collections.defaultdict(list)
        for src, dst in sorted(tickets, reverse=True):
            graph[src].append(dst)
        route = []

        def visit(city):
            while graph[city]:
                visit(graph[city].pop())
            route.append(city)

        visit("JFK")
        return route[::-1]
TIME O(E·LOG E)SPACE O(E)PYTHON · RACE PACE · 14 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED