题目:

链接: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. for循环嵌套练习题or99乘法表

    //输出1-10之间的和 public static void whileTest(){ //定义变量用于存储不断变化的和 int sum = 0; //定义变量,用于记录不断变化的被加数 int x ...

  2. python filter函数(40)

    一.filter函数简介 filter函数主要用来筛选数据,过滤掉不符合条件的元素,并返回一个迭代器对象,如果要转换为列表list或者元祖tuple,可以使用内置函数list() 或者内置函数tupl ...

  3. day18 正则表达式初学

    正则规则:客观存在的,世界上任何一种语言都能使用它. 在线测试网址:http://tool.chinaz.com/regex 正则语句:只和字符串相关,需要考虑的是:在同一个位置上可以出现的字符范围 ...

  4. 使用elementui树形控件写项目小结

    使用tree pagination serch table 实现功能 项目难点主要解析后台传递的代码,线性转树形,这儿加上一个大神的解析 https://blog.csdn.net/dandanzmc ...

  5. css3元素如何扭曲、移位或旋转

    css3 transform 兼容性:IE10+ transform:rotate(deg) 正数为顺时针,负数为逆时针 <!DOCTYPE html> <html lang=&qu ...

  6. 使用expect实现自动交互,shell命令行自动输入

    背景 有需求,在允许命令或者脚本跳出交互行,需要进行内容输入,但需要人手动输入,不是很方便,此时可以通过expect来实现自动互动交互. expect是一个自动交互功能的工具,可以满足代替我们实际工作 ...

  7. 剑指offer-面试题5-替换空格-字符串

    /* 题目: 请实现一个函数,把字符串中的每个空格替换成'%20'. 例如输入“We are happy",则输出 ”We%20are%happy". */ /* 结题思路: 考虑 ...

  8. 【python基础语法】第1天作业练习题

    # 1.下面那些不能作为标识符? """ 1.find 2. _num 3.7val 4.add. 5.def 6.pan 7.-print 8.open_file 9. ...

  9. 铭飞MCMS将4.6模板标签升级至4.7

    个人博客 地址:https://www.wenhaofan.com/article/20190610145529 介绍 MCMS提供的模板大多数都使用的是4.6版本的标签,但是现在MCMS最新的已经是 ...

  10. linux查看硬件、系统信息

    查看机器型号等 dmidecode 是一个读取电脑 DMI(桌面管理接口(Desktop Management Interface))表内容并且以人类可读的格式显示系统硬件信息的工具.这个表包含系统硬 ...