Word Ladder – Solution & Complexity

Solution Walkthrough

  1. Step 1: Turn words into a graph

    • Each word is a node, and there is an edge between two words if they differ by exactly one character.
    • Because every edge has equal cost, shortest path means breadth-first search, not Dijkstra.
  2. Step 2: Brute-force baseline

    • A naive graph build compares every pair of words and connects those with Hamming distance 1. That costs O(n^2 * L).
    • You can do better by generating neighbors of the current BFS word on the fly: change each character to every letter from a through z and see whether the candidate exists in a hash set.
  3. Step 3: BFS for the shortest sequence

    • Put beginWord in a queue with distance 1.
    • Pop words level by level. The first time you reach endWord, return that distance immediately.
    • Remove or mark visited words as soon as you enqueue them so you never revisit the same node.
  4. Step 4: Final solution (all languages)

    The BFS explores each reachable word once, and each exploration tries 26 * wordLength one-letter mutations.

    def ladder_length(beginWord: str, endWord: str, wordList: list[str]) -> int:
        word_set = set(wordList)
        if endWord not in word_set:
            return 0
    
        queue = [(beginWord, 1)]
        head = 0
        if beginWord in word_set:
            word_set.remove(beginWord)
    
        while head < len(queue):
            word, distance = queue[head]
            head += 1
            if word == endWord:
                return distance
    
            letters = list(word)
            for i in range(len(letters)):
                original = letters[i]
                for code in range(ord('a'), ord('z') + 1):
                    char = chr(code)
                    if char == original:
                        continue
                    letters[i] = char
                    candidate = ''.join(letters)
                    if candidate in word_set:
                        word_set.remove(candidate)
                        queue.append((candidate, distance + 1))
                letters[i] = original
    
        return 0
  5. Step 5: Common mistakes and follow-ups

    • Using DFS instead of BFS and accidentally returning a non-shortest path.
    • Forgetting to mark words visited when enqueuing them, which can cause exponential duplication in the queue.
    • Follow-up: bidirectional BFS can shrink the search frontier dramatically on large dictionaries because it grows simultaneously from both ends.

FAQ