Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that: 1) Only one letter can be changed at a time, 2) Each intermediate word must exist in the dictionary.
OR
A transformation sequence from word beginWord to word endWord using a dictionary wordList is a sequence of words beginWord -> s1 -> s2 -> ... -> sk such that:
Every adjacent pair of words differs by a single letter.
Every si for 1 <= i <= k is in wordList. Note that beginWord does not need to be in wordList.
sk == endWord
Given two words, beginWord and endWord, and a dictionary wordList, return all the shortest transformation sequences frombeginWordtoendWord, or an empty list if no such sequence exists. Each sequence should be returned as a list of the words[beginWord, s1, s2, ..., sk].
Input: beginWord ="hit", endWord ="cog", wordList =["hot","dot","dog","lot","log","cog"]Output: [["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]Explanation: There are 2 shortest transformation sequences:"hit"->"hot"->"dot"->"dog"->"cog""hit"->"hot"->"lot"->"log"->"cog"
Example 2:
1
2
3
Input: beginWord ="hit", endWord ="cog", wordList =["hot","dot","dog","lot","log"]Output: []Explanation: The endWord "cog"is not in wordList, therefore there is no valid transformation sequence.
We use BFS to find the shortest path distances from the start word to every reachable word, then use DFS to backtrack and collect all shortest transformation sequences. BFS ensures we only consider shortest paths, and DFS reconstructs all valid sequences.
classSolution {
funfindLadders(beginWord: String, endWord: String, wordList: List<String>): List<List<String>> {
val dict = wordList.toHashSet()
val ans = mutableListOf<List<String>>()
if (!dict.contains(endWord)) return ans
val dist = mutableMapOf<String, Int>()
val q: Queue<String> = LinkedList()
q.offer(beginWord)
dist[beginWord] = 0while (q.isNotEmpty()) {
val w = q.poll()
val d = dist[w]!!for (i in w.indices) {
val arr = w.toCharArray()
for (c in'a'..'z') {
arr[i] = c
val nw = String(arr)
if (dict.contains(nw) && !dist.containsKey(nw)) {
dist[nw] = d + 1 q.offer(nw)
}
}
}
}
if (!dist.containsKey(endWord)) return ans
fundfs(w: String, path: MutableList<String>) {
if (w == beginWord) {
ans.add(path.reversed())
return }
for (i in w.indices) {
val arr = w.toCharArray()
for (c in'a'..'z') {
arr[i] = c
val nw = String(arr)
if (dist[nw] !=null&& dist[nw]!! + 1== dist[w]) {
path.add(nw)
dfs(nw, path)
path.removeAt(path.size - 1)
}
}
}
}
dfs(endWord, mutableListOf(endWord))
return ans
}
}
classSolution:
deffindLadders(self, beginWord: str, endWord: str, wordList: list[str]) -> list[list[str]]:
dict_set: set[str] = set(wordList)
ans: list[list[str]] = []
if endWord notin dict_set:
return ans
dist: dict[str, int] = {}
q: list[str] = [beginWord]
dist[beginWord] =0while q:
w = q.pop(0)
d = dist[w]
for i in range(len(w)):
for c in'abcdefghijklmnopqrstuvwxyz':
nw = w[:i] + c + w[i+1:]
if nw in dict_set and nw notin dist:
dist[nw] = d +1 q.append(nw)
if endWord notin dist:
return ans
defdfs(w: str, path: list[str]):
if w == beginWord:
ans.append(path[::-1])
returnfor i in range(len(w)):
for c in'abcdefghijklmnopqrstuvwxyz':
nw = w[:i] + c + w[i+1:]
if nw in dist and dist[nw] +1== dist[w]:
dfs(nw, path + [nw])
dfs(endWord, [endWord])
return ans