chapter-four/0100~0199/0126.Word-Ladder-II
126. Word Ladder II
题目
Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
- Only one letter can be changed at a time
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:
- Return an empty list if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
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.
题目大意
给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
说明:
- 如果不存在这样的转换序列,返回一个空列表。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
解题思路
- 这一题是第 127 题的加强版,除了找到路径的长度,还进一步要求输出所有路径。解题思路同第 127 题一样,也是用 BFS 遍历。
- 当前做法不是最优解,是否可以考虑双端 BFS 优化,或者迪杰斯塔拉算法?
代码
package leetcode func findLadders(beginWord string, endWord string, wordList []string) [][]string { result, wordMap := make([][]string, 0), make(map[string]bool) for _, w := range wordList { wordMap[w] = true } if !wordMap[endWord] { return result } // create a queue, track the path queue := make([][]string, 0) queue = append(queue, []string{beginWord}) // queueLen is used to track how many slices in queue are in the same level // if found a result, I still need to finish checking current level cause I need to return all possible paths queueLen := 1 // use to track strings that this level has visited // when queueLen == 0, remove levelMap keys in wordMap levelMap := make(map[string]bool) for len(queue) > 0 { path := queue[0] queue = queue[1:] lastWord := path[len(path)-1] for i := 0; i < len(lastWord); i++ { for c := 'a'; c <= 'z'; c++ { nextWord := lastWord[:i] + string(c) + lastWord[i+1:] if nextWord == endWord { path = append(path, endWord) result = append(result, path) continue } if wordMap[nextWord] { // different from word ladder, don't remove the word from wordMap immediately // same level could reuse the key. // delete from wordMap only when currently level is done. levelMap[nextWord] = true newPath := make([]string, len(path)) copy(newPath, path) newPath = append(newPath, nextWord) queue = append(queue, newPath) } } } queueLen-- // if queueLen is 0, means finish traversing current level. if result is not empty, return result if queueLen == 0 { if len(result) > 0 { return result } for k := range levelMap { delete(wordMap, k) } // clear levelMap levelMap = make(map[string]bool) queueLen = len(queue) } } return result }