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.
解题思路:
这道题可以用bfs进行解答。
但是要注意如何防范环的出现以及进行剪枝。
我一开始想的是对于每一条路径,把倒数第二个节点放到访问过的集合中。
因为在倒数第二个节点我们一定是枚举过的,所以它如果能到达重点,也是第一次出现的时候最短。
然后对于每一个单词,对每一个位置进行探测:改变它看看单词是否存在在字典里,并且检查是否访问过(出现在visited set里面)
但是它超时了。。。就很奇怪。
然后看了大佬的解法,大佬是在新的长度时将之前访问过的节点都从给出字典中删除来进行剪枝。对每一层只需要进行一次剪枝操作,可能会更快?
代码取自GrandYang给出的解法
代码:
class Solution { public: vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) { //Because we want to find the shortest path to the end word, so we can use bfs to do searching //To do bfs we will use a queue to hold every nodes, cause we want to return the shortest path //I decided to use another queue to store possible path. vector<vector<string>> res; unordered_set<string> dict(wordList.begin(), wordList.end()); vector<string> p{beginWord}; queue<vector<string>> paths; paths.push(p); int level = 1, minLevel = INT_MAX; unordered_set<string> words; while (!paths.empty()) { auto t = paths.front(); paths.pop(); if (t.size() > level) { for (string w : words) dict.erase(w); words.clear(); level = t.size(); if (level > minLevel) break; } string last = t.back(); for (int i = 0; i < last.size(); ++i) { string newLast = last; for (char ch = 'a'; ch <= 'z'; ++ch) { newLast[i] = ch; if (!dict.count(newLast)) continue; words.insert(newLast); vector<string> nextPath = t; nextPath.push_back(newLast); if (newLast == endWord) { res.push_back(nextPath); minLevel = level; } else paths.push(nextPath); } } } return res; } private: void print(vector<string> &v){ for(auto s : v){ std::cout << s << " "; } std::cout << endl; } };