i:
/* * @lc app=leetcode.cn id=127 lang=cpp * * [127] 单词接龙 * * https://leetcode-cn.com/problems/word-ladder/description/ * * algorithms * Hard (45.95%) * Likes: 738 * Dislikes: 0 * Total Accepted: 104.9K * Total Submissions: 226.9K * Testcase Example: '"hit" "cog" ["hot","dot","dog","lot","log","cog"]' * * 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列: * * * 序列中第一个单词是 beginWord 。 * 序列中最后一个单词是 endWord 。 * 每次转换只能改变一个字母。 * 转换过程中的中间单词必须是字典 wordList 中的单词。 * * * 给你两个单词 beginWord 和 endWord 和一个字典 wordList ,找到从 beginWord 到 endWord 的 最短转换序列 * 中的 单词数目 。如果不存在这样的转换序列,返回 0。 * * * 示例 1: * * * 输入:beginWord = "hit", endWord = "cog", wordList = * ["hot","dot","dog","lot","log","cog"] * 输出:5 * 解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。 * * * 示例 2: * * * 输入:beginWord = "hit", endWord = "cog", wordList = * ["hot","dot","dog","lot","log"] * 输出:0 * 解释:endWord "cog" 不在字典中,所以无法进行转换。 * * * * 提示: * * * 1 * endWord.length == beginWord.length * 1 * wordList[i].length == beginWord.length * beginWord、endWord 和 wordList[i] 由小写英文字母组成 * beginWord != endWord * wordList 中的所有字符串 互不相同 * * */
输出最短路径长度,可以使用bfs的思路,使用queue来记录当前step的所有单词,然后对每个单词遍历长度及a-z,如果处于dict中则塞入队列并从dict中删除,记得beginWord也算1
class Solution { public: int ladderLength(string beginWord, string endWord, vector<string>& wordList) { int step=0; set<string> m; for(string s:wordList){ m.insert(s); } if(m.count(endWord)==0) return 0; queue<string> q; q.push(beginWord); int l=beginWord.size(); while(!q.empty()&&!m.empty()){ step++; int len=q.size(); for(int i=0;i<len;++i){ string word=q.front(); q.pop(); for(int j=0;j<l;++j){ char ch=word[j]; for(int k='a';k<='z';++k){ if(k==ch) continue; word[j]=k; if(word==endWord) return step+1; if(m.count(word)!=0) { m.erase(word); q.push(word); } } word[j]=ch; } } } return 0; } };
ii
/* * @lc app=leetcode.cn id=126 lang=cpp * * [126] 单词接龙 II * * https://leetcode-cn.com/problems/word-ladder-ii/description/ * * algorithms * Hard (39.17%) * Likes: 422 * Dislikes: 0 * Total Accepted: 31K * Total Submissions: 80.6K * Testcase Example: '"hit" "cog" ["hot","dot","dog","lot","log","cog"]' * * 给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord * 的最短转换序列。转换需遵循如下规则: * * * 每次转换只能改变一个字母。 * 转换后得到的单词必须是字典中的单词。 * * * 说明: * * * 如果不存在这样的转换序列,返回一个空列表。 * 所有单词具有相同的长度。 * 所有单词只由小写字母组成。 * 字典中不存在重复的单词。 * 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。 * * * 示例 1: * * 输入: * beginWord = "hit", * endWord = "cog", * wordList = ["hot","dot","dog","lot","log","cog"] * * 输出: * [ * ["hit","hot","dot","dog","cog"], * ["hit","hot","lot","log","cog"] * ] * * * 示例 2: * * 输入: * beginWord = "hit" * endWord = "cog" * wordList = ["hot","dot","dog","lot","log"] * * 输出: [] * * 解释: endWord "cog" 不在字典中,所以不存在符合要求的转换序列。 * */
需要记录所有最短路径的单词
这里记录路径的时候使用path[parent] vertor,来记录parent的所有后续单词。记录时使用bfs,然后输出路径的时候使用dfs。
这里需要注意,不能使用queue来进行bfs遍历,因为如果parent1的后续中有endWord的话,parent2的后续也有endWord,但是此时dict已经删除了endWord,会使得parent2无法被记录。因此使用unordered_set current ,next来记录当前以及下一步的单词,在记录完成路径后从dict中删除之前的next
class Solution { public: vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) { unordered_set<string> dict(wordList.begin(), wordList.end()),cur,next; if(dict.find(endWord)==dict.end()) return {}; vector<vector<string>> ladders; vector<string> ladder; ladder.push_back(beginWord); unordered_map<string, vector<string>> path; int l=beginWord.size(); cur.insert(beginWord); while(true){ for(string s:cur){ dict.erase(s); } for(string s:cur){ string parent=s; for(int i=0;i<l;++i){ char ch=s[i]; for(char j='a';j<='z';++j){ s[i]=j; if(dict.find(s)!=dict.end()){ path[parent].push_back(s); next.insert(s); } } s[i]=ch; } } if(next.empty()) break; if(next.find(endWord)!=next.end()){ genLadders(beginWord,endWord,ladders,ladder,path); return ladders; } cur.clear(); swap(cur,next); } return ladders; } void genLadders(string beginWord, string endWord, vector<vector<string>>& ladders, vector<string> &ladder,unordered_map<string, vector<string>>& path){ if(beginWord==endWord){ ladders.push_back(ladder); return; } for(int i=0;i<path[beginWord].size();++i){ string word=path[beginWord][i]; ladder.push_back(word); genLadders(word,endWord,ladders,ladder,path); ladder.pop_back(); } } };