Word Ladder hard
Problem Statement
Given two words, beginWord
and endWord
, and a dictionary's word list wordList
, return the shortest transformation sequence from beginWord
to endWord
, such that:
- Only one letter can be changed at a time.
- Each intermediate word must exist in the
wordList
.
If there is no such transformation sequence, return an empty array.
Example 1
Input: beginWord = "hit"
, endWord = "cog"
, wordList = ["hot","dot","dog","lot","log","cog"]
Output: ["hit","hot","dot","dog","cog"]
Explanation: "hit" -> "hot" -> "dot" -> "dog" -> "cog"
is the shortest transformation sequence.
Example 2
Input: beginWord = "hit"
, endWord = "cog"
, wordList = ["hot","dot","dog","lot","log"]
Output: []
Explanation: The endWord "cog" is not in wordList, therefore no valid transformation sequence exists.
Steps
-
Initialization: Add
beginWord
to a queuequeue
and a setvisited
. Initialize a variableresult
to store the transformation sequence (initially an array containingbeginWord
). -
Breadth-First Search (BFS): While the
queue
is not empty:- Dequeue the current word
currentWord
. - If
currentWord
is equal toendWord
, the transformation sequence is found. Returnresult
. - Generate all possible one-letter different words from
currentWord
. - For each generated word:
- If the word is in
wordList
and not invisited
:- Enqueue the word.
- Add the word to
visited
. - Add the word to a new array
newResult
which will store the updated transformation sequence.
- If the word is in
- Dequeue the current word
-
Update Result: After processing all neighbors of
currentWord
, updateresult
withnewResult
. -
No Transformation Sequence: If the loop completes without finding
endWord
, return an empty array.
Explanation
The algorithm uses Breadth-First Search (BFS) to find the shortest path. BFS guarantees that the first time we encounter the endWord
, we've found the shortest path because it explores all words at a given distance from the beginWord
before moving to words further away. The visited
set prevents cycles and redundant explorations.
Code
function findLadders(beginWord: string, endWord: string, wordList: string[]): string[][] {
const wordSet = new Set(wordList);
if (!wordSet.has(endWord)) return [];
const queue: [string, string[]] = [[beginWord, [beginWord]]];
const visited = new Set<string>();
visited.add(beginWord);
let result: string[][] = [];
while (queue.length > 0) {
const [currentWord, path] = queue.shift()!;
if (currentWord === endWord) {
result.push(path);
continue; //Found a path, but continue to search for shorter ones.
}
for (let i = 0; i < currentWord.length; i++) {
for (let j = 0; j < 26; j++) {
const charCode = 'a'.charCodeAt(0) + j;
const newWord = currentWord.substring(0, i) + String.fromCharCode(charCode) + currentWord.substring(i + 1);
if (wordSet.has(newWord) && !visited.has(newWord)) {
queue.push([newWord, [...path, newWord]]);
visited.add(newWord);
}
}
}
}
//Return only the shortest paths
if (result.length > 0) {
let shortestLength = result[0].length;
return result.filter(path => path.length === shortestLength);
}
return [];
}
Complexity
- Time Complexity: O(M * N * 26), where M is the length of words and N is the number of words in the word list. We iterate through each word and each position in the word to explore possible transformations.
- Space Complexity: O(M * N) in the worst case, due to the
visited
set and the queue which could potentially store all words in the word list. In practice, it will often be less than this.