Command Palette

Search for a command to run...

Problem 21.6 · Breadth-First SearchHard

Word Ladder

What it teaches: An implicit graph of words, with neighbours generated by changing one letter at a time.

Practise it on judges as “Word Ladder”.

The problem

Transform beginWord into endWord by changing one letter at a time, where every intermediate word must be in wordList. Return the number of words in the shortest sequence (including both ends), or 0 if impossible.

Example 1

Input: hit → cog, wordList = [hot,dot,dog,lot,log,cog]
Output: 5

hit → hot → dot → dog → cog.

Constraints

  • 1 ≤ word length ≤ 10
  • 1 ≤ wordList ≤ 5000

Pattern clues in the wording

  • → Fewest one-step transformations

These clues point to Graph BFS: Explore from a start node in rings of increasing distance using a queue and a visited set.

Stuck? Take one hint at a time

Solution.java · starter
import java.util.*;

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        return 0;
    }
}

Write your solution locally or in your editor for now. The in-browser runner (Java first, then Python, C++ and more) will run these tests right here.

Test cases

#InputExpected
1
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
5
2
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
0

+ 1 hidden test the code runner will check

From slow to fast

Approaches

1

BFS with letter substitution

Time O(N × L × 26) Space O(N × L)

Put the word list in a set (return 0 if endWord is missing). BFS from beginWord; remove words from the set when enqueued so they're visited once.

Approach 1
import java.util.*;

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> dict = new HashSet<>(wordList);
        if (!dict.contains(endWord)) return 0;
        Deque<String> q = new ArrayDeque<>();
        q.offer(beginWord);
        dict.remove(beginWord);
        for (int len = 1; !q.isEmpty(); len++) {
            for (int size = q.size(); size > 0; size--) {
                String w = q.poll();
                if (w.equals(endWord)) return len;
                char[] c = w.toCharArray();
                for (int i = 0; i < c.length; i++) {
                    char orig = c[i];
                    for (char ch = 'a'; ch <= 'z'; ch++) {
                        if (ch == orig) continue;
                        c[i] = ch;
                        String t = new String(c);
                        if (dict.remove(t)) q.offer(t);
                    }
                    c[i] = orig;
                }
            }
        }
        return 0;
    }
}

Verdict: Generating neighbours beats comparing every pair of words (O(N² L)).

Before you submit

Edge cases and common mistakes

Test these inputs

  • endWord not in the list
  • beginWord already equals a list word

Mistakes people make

  • Comparing every pair of words to build edges.
  • Not removing visited words (exponential revisits).

Interview

Follow-up questions

How would you return all shortest sequences (Word Ladder II)?