题目:

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

    import: html文件中,通过script标签引入js文件. 而vue中,通过import xxx from xxx路径的方式导入文件,不光可以导入js文件. "xxx"指的 ...

  2. cobaltstrike使用笔记2

    0x01 cs服务端绕过流量检测 定义C2的通信格式,修改CS默认的流量特征 编写Profiles: 开源Profiles:https://github.com/rsmudge/Malleable-C ...

  3. ipad的12系统里提示更新到ipdos13,原来安装在12上的app是不是没有了,要重新下载

    ipad的12系统里提示更新到ipdos13,原来安装在12上的app是不是没有了,要重新下载 更新后原来的WiFi密码都还在不用重新连接WiFi,桌面壁纸也是原来12系统上的 在Ipad的设置里将1 ...

  4. Java Web Servlet知识点讲解(一)

    一.Web应用架构 如图所示: HTTP协议:一个简单的请求一响应协议,通常运行在TCP之上,它指定了客户端可能发送给服务器什么样的信息以及得到什么样的响应. JDBC:Java语言中用来规范客户端程 ...

  5. PPT、Word、Excel模板免费下载

    本篇文章可能只有寥寥数字,但他的作用可能很大,可能帮助到很多朋友.本人喜欢搜集一些资源,也爱免费分享,因为好东西我藏不住,总感觉分享出来更快乐. 网址:https://www.bangongziyua ...

  6. adworld python-trade | python反编译

    附件是.pyc格式的文件. Python程序中,原始程序代码存储在.py文件里,而Python会在执行.py文件的时候,会将.py形式的程序编译成中间式文件(byte-compiled)的.pyc文件 ...

  7. [Python] 前程无忧招聘网爬取软件工程职位 网络爬虫 https://www.51job.com

    首先进入该网站的https://www.51job.com/robots.txt页面 给出提示: 找不到该页 File not found 您要查看的页已删除,或已改名,或暂时不可用. 请尝试以下操作 ...

  8. 【剑指Offer】61、把二叉树打印成多行

    题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 题解一:BFS public static ArrayList<ArrayList<Integer>> ...

  9. 聊聊SNMP协议

    注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 本文源链接:https://www.cnblogs.com/chloneda/p/snmp-protoco ...

  10. LVS负载均衡工作模式和调度算法

    原文链接:https://blog.csdn.net/weixin_40470303/article/details/80541639 一.LVS简介 LVS(Linux Virtual Server ...