Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
Note:
Example 1:
Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
Output:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Example 2:
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: []
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
This is just like 127. Word Ladder.
The constrain still works, but instead of deleting the words right away, collect them and delete them all when a level ends, so that we can reuse the words (matching different parents in the same level).
The items in the queue are not just words now. Parent nodes are also kept so that we can backtrack the path from the end.
/**
* @param {string} beginWord
* @param {string} endWord
* @param {string[]} wordList
* @return {string[][]}
*/
function findLadders (beginWord, endWord, wordList) {
wordList = new Set(wordList)
if (!wordList.has(endWord)) { return [] }
const ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
const result = []
let isEndWordFound = false
const levelWords = new Set()
const queue = [[beginWord, null], null]
while (queue.length > 1) {
const node = queue.shift()
if (node === null) {
if (isEndWordFound) {
break
}
levelWords.forEach(word => wordList.delete(word))
levelWords.clear()
queue.push(null)
continue
}
const word = node[0]
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 w = head + ALPHABET[c] + tail
if (w === endWord) {
const path = [endWord]
for (let n = node; n !== null; n = n[1]) {
path.unshift(n[0])
}
result.push(path)
isEndWordFound = true
}
if (wordList.has(w)) {
levelWords.add(w)
queue.push([w, node])
}
}
}
}
}
return result
};
Template generated via Leetmark.