第四周:[leetcode] 126. Word Ladder II
来源:互联网 发布:空降什么意思网络 编辑:程序博客网 时间:2024/05/22 08:28
题目链接:链接
题目描述:在wordList中寻找从beginWord到endWord的最短转换序列,要求每次转化只能变换一个字符。
Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”,”cog”]Return
[
[“hit”,”hot”,”dot”,”dog”,”cog”],
[“hit”,”hot”,”lot”,”log”,”cog”]
]
解题思路:一开始以先解题目,后考虑空间、效率的目的,没有过多考虑,写了个DFS + 截枝的思路,算法实现较为简单,但效率过低,在跑list.size() > 100的测试用例时TLE,Solution1代码如下:
Solution1://判断是否能从pre转化为curbool canChange(string pre, string cur, vector<string>& sub){ for(int i = 0; i < sub.size(); i++){ if(cur == sub[i])return false; } //有一个字符不同即可以转化 int count = 0; for(int i = 0; i < pre.length(); i++){ if(pre[i] != cur[i])count++; if(count > 1)return false; } return count == 1;}void findLadder(string end, vector<string>& list, vector<vector<string>>& res, vector<string>& sub){ string cur = sub.back(); //能转换到wordEnd则加入result容器 if(cur == end){ if(res.empty() || res[0].size() == sub.size()) res.push_back(sub); else if(res[0].size() > sub.size()){ res.clear(); res.push_back(sub); } return; } //如果转换列表的长度大于当前res容器存储列表的长度,则返回,实现截枝 if(res.size() != 0 && res[0].size() <= sub.size())return; //递归查找 for(int i = 0; i < list.size(); i++){ if(canChange(cur, list[i], sub)){ sub.push_back(list[i]); findLadder(end, list, res, sub); sub.pop_back(); } }}vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) { vector<vector<string>> res; vector<string> sub; sub.push_back(beginWord); findLadder(endWord, wordList, res, sub); return res;}
算法分析:
1. 编写代码时就注意到效率最低肯定在递归查找,每次递归都进行O(n)时间寻找,效率极低,可建立unordered_map映射,保存所有已搜寻过的可转换序列加入列表,先从列表查找;
2. canChange函数判断是否能从pre转化为cur,vector数据结构的遍历也为O(n1)时间;可用红黑树实现的unordered_set数据结构,查找效率为O(log(n1));
3. 算法本身性质问题,深度搜索不保证第一次搜寻的就是最短序列,广度优先搜寻所有最优解更合适。
针对以上问题,进行改进:现广度优先搜索生成树,后进行路径生成,得解!但是,在更大更大更大数量的测试下还是差在时间问题!!!再次思考数据结构的问题···通过漫长漫长的思考以及网上的学习,发现可进行以下思路进行改进:
1.运用两个unordered_set数据结构,保存生成树前一高度与当前高度的字符串,交替变换,可将已在树中的string从list中删除,保证父树不重复出现在子树节点中;如(1)a->b,b->c,(2)a->c的情况,当广度搜寻完c时,把c删除,截去情况(1);
2.判断子节点方面,逐位置改变父节点的字符进行判断,建树效率为str.length*26*log(n)(平衡二叉树查找),而Solution1对list遍历进行查找,其效率为stri.length*n;
奋战近1.5天,Solution2解题如下(176ms AC):
网上见有88ms,56msAC的方法,休息片刻,再继续学习~总而言之,编程量较大的题目思考收获挺多的~
void findPath(string now, string end, vector<string>& sub, unordered_map<string, vector<string>>& path, vector<vector<string>>& res){ if(now == end){ sub.push_back(now); vector<string> t = sub; reverse(t.begin(), t.end()); res.push_back(t); sub.pop_back(); return; } for(int i = 0; i < path[now].size(); i++){ sub.push_back(now); findPath(path[now][i], end, sub, path, res); sub.pop_back(); }}vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) { vector<vector<string>> res; unordered_set<string> list(wordList.begin(), wordList.end()); unordered_map<string, vector<string>> path; vector<unordered_set<string>> layer(2); int cur = 0; int pre = 1; list.insert(beginWord); layer[cur].insert(beginWord); while(true){ swap(cur, pre); layer[cur].clear(); for(unordered_set<string>::iterator iter = layer[pre].begin(); iter != layer[pre].end(); iter++){ list.erase(*iter); string t = *iter; for(int i = 0; i < (*iter).size(); i++){ string word = *iter; int stop = word[i] - 'a'; for(int j = (stop + 1)%26; j != stop; j = (j+1) % 26){ word[i] = j + 'a'; //layer[pre].find(word) == layer[pre].end()除去寻找过程中已保存在pre的情况 if(list.find(word) != list.end() && layer[pre].find(word) == layer[pre].end()){ layer[cur].insert(word); path[word].push_back(*iter); } } } } if(layer[cur].size() == 0){ return res; } if(layer[cur].find(endWord) != layer[cur].end()){ break; } } vector<string> sub; //从endWord到beginWord查找 findPath(endWord, beginWord, sub, path, res); return res;}
- 第四周:[leetcode] 126. Word Ladder II
- [Leetcode] 126. Word Ladder II
- [leetcode] 126.Word Ladder II
- leetcode 126. Word Ladder II
- Leetcode 126. Word Ladder II
- Leetcode 126. Word Ladder II
- [leetcode] 126. Word Ladder II
- [LeetCode] 126. Word Ladder II
- 【LeetCode】126. Word Ladder II
- LeetCode 126. Word Ladder II
- LeetCode 126. Word Ladder II
- Leetcode 126. Word Ladder II
- leetcode 126. Word Ladder II
- leetcode 126. Word Ladder II
- Leetcode 126. Word Ladder II
- leetcode 126. Word Ladder II
- Leetcode 127. Word Ladder I & 126. Word Ladder II
- 126. Word Ladder II 、 127. Word Ladder(leetcode BFS+DFS)
- 还是CSDN好用
- linux之vim文本编辑器补充
- C++ Primer_4th学习笔记(1)
- 【Leetcode】541. Reverse String II
- 每天一个Linux命令(11):nl命令
- 第四周:[leetcode] 126. Word Ladder II
- 微信小程序学习用demo推荐:读书;小清新
- Zookeeper与Kafka集群搭建
- (51nod)1003
- Android中的Handler
- bootcamp 没有创建 win7 win8 安装盘
- ZOJ1140&&POJ1469&&HDU1083-Courses
- Python安装第三方模块
- 底层I/O的操作过程