Word Ladder — Solution in Python, Java & C++
Word Ladder solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript. A hard problem, asked at Amazon and Google.
Word Ladder is a hard coding problem on strings, hash table and breadth-first search, asked in Amazon, Google, Microsoft and Meta interviews.
- Difficulty: Hard
- Topics: Strings, Hash Table, Breadth-First Search
- Asked at: Amazon, Google, Microsoft, Meta, Snapchat, Yelp, Ola, LinkedIn, Spotify, Arcesium
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
A transformation sequence from beginWord to endWord is a chain of words where every adjacent pair differs by exactly one letter and every word after the first appears in wordList.
Return the number of words in the shortest such sequence, or 0 if none exists.
Example 1
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Example 2
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: endWord is not in wordList.
Example 3
Input: beginWord = "a", endWord = "c", wordList = ["a","b","c"]
Output: 2
Constraints
1 <= beginWord.length <= 6All words have the same length.1 <= wordList.length <= 20beginWord != endWordAll words consist of lowercase English letters.
Hints for Word Ladder
Hint 1
Every transformation costs the same, so breadth-first search finds the shortest chain.
Hint 2
Expand a word to every unused list entry that differs from it in exactly one position.
Hint 3
Count words rather than steps: the answer is one more than the number of transformations.
How to solve Word Ladder
BFS over words where an edge is a one-letter difference; the level count is the number of words in the chain.
Approach
- Frontier =
[beginWord],level = 1. - Expand each word to unused list entries with exactly one differing position; return
level + 1on reachingendWord. - Return 0 if exhausted.
Why it works
Uniform edge cost makes BFS optimal, and counting levels from 1 yields the number of words rather than transformations.
Complexity
- Time —
O(levels · |list| · L) - Space —
O(|list|)
Pitfalls
- For large lists, generate the
26 · Lneighbours of each word and look them up in a set instead of scanning the list.
Reference solution
Python
def ladderLength(beginWord: str, endWord: str, wordList) -> int:
used = [False] * len(wordList)
frontier = [beginWord]
level = 1
while frontier:
nxt = []
for word in frontier:
for i, candidate in enumerate(wordList):
if used[i]:
continue
diff = sum(1 for a, b in zip(candidate, word) if a != b)
if diff != 1:
continue
if candidate == endWord:
return level + 1
used[i] = True
nxt.append(candidate)
frontier = nxt
level += 1
return 0Java
public static int ladderLength(String beginWord, String endWord, String[] wordList) {
boolean[] used = new boolean[wordList.length];
List<String> frontier = new ArrayList<>();
frontier.add(beginWord);
int level = 1;
while (!frontier.isEmpty()) {
List<String> next = new ArrayList<>();
for (String word : frontier) {
for (int i = 0; i < wordList.length; i++) {
if (used[i]) continue;
int diff = 0;
for (int k = 0; k < wordList[i].length(); k++) {
if (wordList[i].charAt(k) != word.charAt(k)) diff++;
}
if (diff != 1) continue;
if (wordList[i].equals(endWord)) return level + 1;
used[i] = true;
next.add(wordList[i]);
}
}
frontier = next;
level++;
}
return 0;
}C++
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
vector<bool> used(wordList.size(), false);
vector<string> frontier;
frontier.push_back(beginWord);
int level = 1;
while (!frontier.empty()) {
vector<string> next;
for (const string& word : frontier) {
for (size_t i = 0; i < wordList.size(); i++) {
if (used[i]) continue;
int diff = 0;
for (size_t k = 0; k < wordList[i].size(); k++) {
if (wordList[i][k] != word[k]) diff++;
}
if (diff != 1) continue;
if (wordList[i] == endWord) return level + 1;
used[i] = true;
next.push_back(wordList[i]);
}
}
frontier = next;
level++;
}
return 0;
}JavaScript
var ladderLength = function(beginWord, endWord, wordList) {
const used = wordList.map(function() { return false; });
let frontier = [beginWord];
let level = 1;
while (frontier.length > 0) {
const next = [];
for (let f = 0; f < frontier.length; f++) {
for (let i = 0; i < wordList.length; i++) {
if (used[i]) continue;
let diff = 0;
for (let k = 0; k < wordList[i].length; k++) {
if (wordList[i].charAt(k) !== frontier[f].charAt(k)) diff++;
}
if (diff !== 1) continue;
if (wordList[i] === endWord) return level + 1;
used[i] = true;
next.push(wordList[i]);
}
}
frontier = next;
level++;
}
return 0;
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 515 strings problems · the whole catalogue
Learn the technique: Strings · Hashing: Hash Maps and Hash Sets