◀ THE GRIND — GRAPHS

Word Ladder

The drill: Transform a start word into a target word one letter swap at a time, where every intermediate word must exist in a given dictionary — find the fewest words needed for such a chain, or report that none exists.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A start word and an end word share the same length, and a dictionary of same-length words sits between them. The drill is to hop from the start to the end one word at a time, changing exactly one letter per hop.

Every word visited along the way — except the start — has to already exist in that dictionary. The start word itself is free to be outside it, but every hop after that lands only on dictionary entries.

The task is the length of the shortest such chain, counting the start word as the first entry and the end word as the last. If no sequence of one-letter hops can reach the end word through the dictionary, the chain doesn't exist.

EX 01
beginWord = "cat" · endWord = "dog" · wordList = ["cot", "cog", "dog", "bat", "bad", "bag"]
4
FORCED SINGLE-LETTER-AT-A-TIME CHAIN: CAT -> COT -> COG -> DOG
EX 02
beginWord = "cat" · endWord = "dog" · wordList = ["cot", "cog", "bat", "bad", "bag"]
0
END WORD MISSING FROM THE DICTIONARY ENTIRELY
EX 03
beginWord = "lead" · endWord = "lend" · wordList = ["lend"]
2
MINIMUM DICTIONARY: ONE WORD, ONE HOP AWAY
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

Treat every word in the dictionary as a node, and draw an edge between two words whenever they differ in exactly one letter. The question is now shortest path in that graph — and shortest path in an unweighted graph has one classic tool.

HINT 2 THE STRUCTURE

You don't have to discover edges by comparing every pair of words. Swap one letter of a word for a wildcard and you get a pattern that every one-hop neighbor shares — group the whole dictionary by those patterns once, up front.

HINT 3 ONE STEP FROM THE ANSWER

Run a breadth-first search from the start word, expanding through the wildcard buckets instead of a pairwise scan. The level at which the target word first appears — counting the start word itself as level one — is the answer; an empty frontier with no target found means no chain exists.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE WILDCARD LADDERPATTERN · BFS — WILDCARD BUCKETScat → dog · dict: cot, cog, dog, bat, bad, bag
QUEUE
cat (1)
STEP 1

Bucket every word by its wildcard pattern, so 'c*t' maps to cat and cot. Level-order BFS from cat finds the shortest ladder to dog.

STEP 1 / 8 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/word-ladder.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
        word_set = set(wordList)
        if endWord not in word_set:
            return 0

        length = len(beginWord)
        buckets = collections.defaultdict(list)
        for word in word_set:
            for i in range(length):
                buckets[word[:i] + "*" + word[i + 1:]].append(word)

        visited = {beginWord}
        queue = collections.deque([(beginWord, 1)])
        while queue:
            word, steps = queue.popleft()
            if word == endWord:
                return steps
            for i in range(length):
                pattern = word[:i] + "*" + word[i + 1:]
                for neighbor in buckets[pattern]:
                    if neighbor not in visited:
                        visited.add(neighbor)
                        queue.append((neighbor, steps + 1))
        return 0
TIME O(N·L²)SPACE O(N·L)PYTHON · RACE PACE · 25 LN

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