Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Note:
Example 1:
Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.
Example 2:
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
Think of it as building a tree, with begineWord
as root and
endWord
as leaves.
The best way control the depth (length of the shortest transformations) while building the tree is level-order traversal (BFS).
We do not actually build the tree because it is expensive (astronomical if
the list is huge). In fact, we only need one shortest path. So just like
Dijkstra’s algorithm, we say that the first time (level i
) we
encounter a word that turns out to be in a shortest path, then level
i
is the lowest level this word could ever get. We can safely
remove it from the wordList
.
To find all the next words, instead of filtering the
wordList
, enumerate all 25 possible words and check if in
wordList
.
/**
* @param {string} beginWord
* @param {string} endWord
* @param {string[]} wordList
* @return {number}
*/
var ladderLength = function(beginWord, endWord, wordList) {
wordList = new Set(wordList)
if (!wordList.has(endWord)) { return 0 }
const ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
let level = 1
const queue = [beginWord, null]
while (queue.length > 1) {
const word = queue.shift()
if (word === null) {
level++
queue.push(null)
continue
}
for (let i = word.length - 1; i >= 0; i--) {
const head = word.slice(0, i)
const tail = word.slice(i+1)
for (let c = 0; c < 26; c++) {
if (ALPHABET[c] !== word[i]) {
const word = head + ALPHABET[c] + tail
if (word === endWord) {
return level + 1
}
if (wordList.delete(word)) {
queue.push(word)
}
}
}
}
}
return 0
};
Template generated via Leetmark.