题目:

链接:https://leetcode-cn.com/problems/word-ladder-ii/

给定两个单词(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" 不在字典中,所以不存在符合要求的转换序列。

解答:

1.首先抽象成图,那么要求的转换序列长度就是beginWord到endWord的最短路径的边数,相邻节点改变一位就互相可达,如:hot和hog,cat和cot等等。所以先建图肯定免不了,我们果断先建立邻接表再说。

2.然后考虑求所有路径,那一般来说肯定得用dfs了。但是直接dfs可能有如下情况:实际最短路径可能就两步,即beginWord---->某单词---->endWord。但给了几百个节点,我们dfs遍历的绝大部分都是无用的,所以考虑需要剪枝处理。

3.接下来想到了先用bfs确定最短路径的长度,再用dfs查找所有的最短路径。但无奈剪枝不够,第31个用例吧好像,最短路径长度是19,基本相当于没剪枝,所以就一直AC不了。

后来看了下面链接的题解,用了一个特别的方法来剪枝:即之前bfs查找最短路径的长度时,用一个哈希表存储每个单词第一次出现的长度,比如有beginWord--->a->b->c,还有beginWord--->c,那么我们从beginWord开始dfs的时候,取其相邻节点时,要检查之前的哈希表,看当前单词是不是第一次出现的位置,如果不是,就没必要考察了,因为肯定不是最短路径。(建议还是去看下面链接,很清楚)

大神题解链接,回头温习,写的真是太牛了:

https://leetcode-cn.com/problems/word-ladder-ii/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-3-3/

代码如下,还是蛮多行的:

 1 class Solution {
2 public:
3 vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
4 if(find(wordList.begin(),wordList.end(),endWord)==wordList.end()){return {};}
5 wordList.emplace_back(beginWord);
6 unordered_map<string,vector<string>> dic;
7 for(string& wd:wordList){
8 string s=wd;
9 for(int i=0;i<s.size();++i){
10 s[i]='#';
11 dic[s].emplace_back(wd);//eg: "hot":分为"#ot","h#t","ho#"
12 s=wd;
13 }
14 }
15 unordered_map<string,unordered_set<string>> graph;//邻接表
16 for(string& wd:wordList){
17 string s=wd;
18 for(int i=0;i<s.size();++i){
19 s[i]='#';
20 for(const string& neighbour:dic[s]){
21 graph[wd].insert(neighbour);
22 }
23 s=wd;
24 }
25 graph[wd].erase(wd);//删除自己
26 }
27 //从endWord开始找,先用BFS找一个最短转换的长度
28 queue<string> que;
29 que.push(endWord);
30 unordered_map<string,int> first_show;//每个单词第一次出现的层数(从endWord倒着算起)
31 unordered_set<string> visited={endWord};//考察过的记录在里面
32 int min_len=0,step=0;
33 string cur;
34 while(not que.empty()){
35 int cur_len=que.size();
36 for(int i=0;i<cur_len;++i){
37 cur=que.front();
38 que.pop();
39 if(first_show.count(cur)==0){
40 first_show[cur]=step;
41 }
42 if(cur==beginWord){//找到起始单词则退出循环
43 min_len=step;
44 break;
45 }
46 for(const string& neighbour:graph[cur]){
47 if(visited.count(neighbour)==0){//一步能到达的邻居,如果没遍历过则放到队尾
48 que.push(neighbour);
49 visited.insert(neighbour);
50 }
51 }
52 }
53 if(cur==beginWord){break;}
54 ++step;
55 }
56 if(min_len==0){return {};}
57 //用DFS找所有长度为min_len的解
58 vector<string> temp={endWord};
59 vector<vector<string>> res;
60 visited.clear();
61 dfs(res,first_show,temp,beginWord,0,min_len,visited,graph);
62 for(auto& vec:res){
63 reverse(vec.begin(),vec.end());
64 }
65 return res;
66 }
67 void dfs(vector<vector<string>>& res,unordered_map<string,int>& first_show,vector<string>&cur,string target,int cur_len,int target_len,unordered_set<string>& visited,unordered_map<string,unordered_set<string>>& graph){
68 if(cur_len>=target_len){
69 if(cur.back()==target){
70 res.emplace_back(cur);
71 }
72 return;
73 }
74 for(const string& nei:graph[cur.back()]){
75 if(visited.count(nei)==0 and first_show[nei]==cur_len+1){
76 cur.emplace_back(nei);
77 visited.insert(nei);
78 dfs(res,first_show,cur,target,cur_len+1,target_len,visited,graph);
79 cur.pop_back();
80 visited.erase(nei);
81 }
82 }
83 }
84 };

126. 单词接龙 II的更多相关文章

  1. Java实现 LeetCode 126 单词接龙 II

    126. 单词接龙 II 给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列.转换需遵循如下规则: ...

  2. Leetcode 126.单词接龙II

    单词接龙II 给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列.转换需遵循如下规则: 每次转换只能 ...

  3. [LeetCode] 126. 单词接龙 II

    题目链接 : https://leetcode-cn.com/problems/word-ladder-ii/ 题目描述: 给定两个单词(beginWord 和 endWord)和一个字典 wordL ...

  4. LeetCode 126. Word Ladder II 单词接龙 II(C++/Java)

    题目: Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transfo ...

  5. [Swift]LeetCode126. 单词接龙 II | Word Ladder II

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  6. lintcode 单词接龙II

    题意 给出两个单词(start和end)和一个字典,找出所有从start到end的最短转换序列 比如: 1.每次只能改变一个字母. 2.变换过程中的中间单词必须在字典中出现. 注意事项 所有单词具有相 ...

  7. 图-搜索-BFS-DFS-126. 单词接龙 II

    2020-03-19 13:10:35 问题描述: 给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序 ...

  8. 单词接龙(dragon)(BFS)

    单词接龙(dragon) 时间限制: 1 Sec  内存限制: 64 MB提交: 12  解决: 5[提交][状态][讨论版] 题目描述 单 词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已 ...

  9. NOIP2000单词接龙[DFS]

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

随机推荐

  1. R语言矩阵维度“消失”的问题

    矩阵(matrix)是R语言中很基础的一种数据结构,也是R语言使用者经常使用的一种数据结构.矩阵的维度一般为二维(m*n). R语言中矩阵的操作是非常简单易懂的,但是在对R语言做矩阵操作时,有个地方需 ...

  2. php压缩文件zip格式并打包(单个或多个文件压缩)

    最近接到一个需求,就是选择多个文件下载时,不要一个一个下载,直接把多个文件打包成一个文件进行下载.我们项目是前后端分离,所以我写了个接口,让前端传参数,后台下载. 废话不多说,直接上代码: 先是压缩单 ...

  3. asp.net mvc 使用AuthorizeAttribute做授权验证

    授权验证,比如登陆验证 1.自定义属性继承AuthorizeAttribute 2.重写OnAuthorization方法 3.通过AllowAnonymousAttribute特性处理无需授权的Ac ...

  4. python—lambda函数,三个常用的高阶函数

    """lambda 参数列表 : 返回值lambda 参数形式: 1.无参数:lambda:100 2.一个参数:lambda a: a 3.默认参数:lambda a, ...

  5. .Net框架的模块代码生成器--其一(dotnet new)

    小白教程声明,首先先介绍一下.Net 框架及模块是什么情况: 1.公司的大佬会把框架的代码打包成Nuget包放在公司的服务器上 2.公司会专门开一个git仓库,存储模块的代码,每个模块都有其独立的文件 ...

  6. vue富文本编辑器vue-quill-editor使用总结(包含图片上传,拖拽,放大和缩小)

    vue-quill-editor是vue很好的富文本编辑器,富文本的功能基本上都支持,样式是黑白色,简洁大方. 第一步下载 vue-quill-editor: npm i vue-quill-edit ...

  7. Linux 文件(持续更新)

    一.文件类型 Linux操作系统把所有内容(文件.图片.视频.设备)都当作文件看待.处理,即一切皆文件. Linux系统把所有文件分为七种类型: 文件类型 文件类型标识 说明 使用ls -l命令查看文 ...

  8. H5_0026:使用CSS里的user-select属性控制用户在页面上选中的内容

    CSS里的user-select属性用来禁止用户用鼠标在页面上选中文字.图片等,也就是,让页面内容不可选.也可以只允许用户选中文字,或者全部都放开,用户可以同时选中文字.还包括文本里的图片.视频等其它 ...

  9. Aspcms标签大全及常用标签

    相关解释:1.首页指的是index.html文件.列表页一般指newslist.html,productlist.html等文件,该文件对应于后台栏目添加或修改时的列表模板.内页一般指news.htm ...

  10. Java数三退一问题

    问题描述 有100人围成一圈,顺序排号.从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位. 代码实现: public class Count3Quit1 { ...