Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:html
Note:post
Example 1:spa
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:code
Input: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] Output: [] Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
這道題是LeetCode 127. Word Ladder 單詞接龍(C++/Java)的擴展,要找出全部最短轉換序列。orm
仍是利用BFS,在每一次搜索的時候都要將單詞之間的轉換記錄下來,利用map進行存儲,例如htm
["hot","dot","dog","lot","log","cog"]
hot能夠改變一個字符轉換爲dot和lot,能夠將單詞和由這個單詞擴展的單詞列表存進map中,方便咱們後續來進行路徑構建。blog
此外咱們要在每一層搜索前將單詞從由單詞序列構建的字典中刪除掉,而不是在找到一個單詞就刪除。並且有的單詞可能會成爲多個單詞的擴展,例如hot和dot均可以擴展爲lot,因此若是當前循環中沒有找到結果,全部有可能構建路徑的單詞都要存進map中,在這一輪搜索完畢後,再將它們從字典中刪除。rem
C++get
class Solution { public: vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) { unordered_set<string> dict; vector<vector<string>> res; for(string s:wordList) dict.insert(s); if(!dict.count(endWord)) return {}; dict.erase(endWord); unordered_set<string> p{beginWord}, q; unordered_map<string, vector<string>> children; int l = beginWord.length(); bool find = false; while(!p.empty() && !find){ for(string s:p) dict.erase(s); for(string str:p){ string word = str; for(int i = 0; i < l; ++i){ char ch = word[i]; for(int j = 'a'; j < 'z'; ++j){ if(ch == j) continue; word[i] = j; if(word == endWord){ find = true; children[str].push_back(word); }else{ if(dict.count(word) && !find){ q.insert(word); children[str].push_back(word); } } } word[i] = ch; } } p.clear(); swap(p, q); } if(find){ vector<string> path{beginWord}; bfs(res, children, path, beginWord,endWord); } return res; } private: void bfs(vector<vector<string>> &res, unordered_map<string, vector<string>> &children, vector<string> path, string beginWord, string endWord){ if(beginWord == endWord){ res.push_back(path); return; } auto it = children.find(beginWord); if(it == children.end()) return; for(string word:it->second){ path.push_back(word); bfs(res, children, path, word, endWord); path.pop_back(); } } };
Javastring
class Solution { public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) { Set<String> dict = new HashSet<>(wordList); List<List<String>> res = new ArrayList<>(); if(!dict.contains(endWord)) return res; Set<String> p = new HashSet<>(); p.add(beginWord); int l = beginWord.length(); HashMap<String, List<String>> children = new HashMap<>(); boolean find = false; while(!p.isEmpty() && !find){ for(String s:p) dict.remove(s); Set<String> q = new HashSet<>(); for(String str:p){ char[] word = str.toCharArray(); for(int i = 0; i < l; ++i){ char ch = word[i]; for(int j = 'a'; j <= 'z'; ++j){ if(j == ch) continue; word[i] = (char)j; String w = new String(word); if(w.equals(endWord)){ find = true; List<String> list = children.getOrDefault(str, new ArrayList<>()); list.add(w); children.put(str, list); }else{ if(dict.contains(w) && !find){ List<String> list = children.getOrDefault(str, new ArrayList<>()); list.add(w); children.put(str, list); q.add(w); } } } word[i] = ch; } } p = q; } if(find){ List<String> path = new ArrayList<>(); path.add(beginWord); bfs(res, path, children, beginWord, endWord); } return res; } private void bfs(List<List<String>> res, List<String> path, HashMap<String, List<String>> children, String beginWord, String endWord){ if(beginWord.equals(endWord)){ res.add(new ArrayList(path)); return; } if(!children.containsKey(beginWord)) return; List<String> list = children.get(beginWord); for(String word:list){ path.add(word); bfs(res, path, children, word, endWord); path.remove(word); } } }