leetcode—word ladder II
1.题目描述
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:Only one letter can be changed at a timeEach intermediate word must exist in the dictionaryFor example,Given:start = "hit"end = "cog"dict = ["hot","dot","dog","lot","log"]Return[["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
2.解题思路
我一看到这个题目就觉得类似于最小生成树,应该用贪心算法来做,贪心算法的思路如下:
从start串出发,找出一次变换可以得到的string串的集合S1,如果集合S1中包含有end串,那么搜索结束,否则,搜索两步之内能到达的串的集合S2,同样判断两步之内能到达的串集合中是否有end串,以此类推,最终找到最短路径。另外,路径保存需要单独设置一个数据结构,
最终算法描述如下(类最小生成树):
- 将字典dict中的所有字符串分为左右两侧,一侧为leftside=start(实际编码不需存储),一侧为rightside=(dict-start),当前距start最远的节点,比如说从start i 步之内可达的节点集合curStep = start (因为初始是0步可达)。
- 计算nextStep,也就是 i+1 步可达的字符串集合,最简单的思路就是下面的思路,遍历curStep 遍历rightside,逐个比较,必然能找到nextStep,找到nextStep之后curStep 变成了nextStep,将nextStep 中的字符串从rightside里面抹去,nextStep清空继续寻找直至找到的nextStep或rightside为空(表示没有路径到end),或者end被发现。
于是有了下面的这份代码:
class Solution {public:vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) {// end typing your C/C++ solution below// DO NOT write int main() function//areslipan@163.commap<string,vector<string> > path;unordered_set<string>leftside;unordered_set<string>rightside=dict;rightside.insert(start);rightside.insert(end);leftside.insert(start);rightside.erase(start);unordered_set<string>curStep;unordered_set<string>nextStep;curStep.insert(start);while(curStep.find(end)==curStep.end()&&!rightside.empty()){unordered_set<string>::iterator iter_us_cur;unordered_set<string>::iterator iter_us_right;for(iter_us_cur=curStep.begin();iter_us_cur!=curStep.end();++iter_us_cur){for(iter_us_right=rightside.begin();iter_us_right!=rightside.end();++iter_us_right){if(isCvtable(*iter_us_cur,*iter_us_right)){if(path.find(*iter_us_cur)!=path.end()){path[*iter_us_cur].push_back(*iter_us_right);}else{vector<string> emptyV;path[*iter_us_cur]=emptyV;path[*iter_us_cur].push_back(*iter_us_right);}nextStep.insert(*iter_us_right);}}}if(nextStep.empty())break;for(iter_us_right=nextStep.begin();iter_us_right!=nextStep.end();++iter_us_right){rightside.erase(*iter_us_right);}curStep = nextStep;nextStep.clear();}vector<vector<string> > result;vector<string> temp;if(curStep.find(end)!=curStep.end()){output(path,start,end,result,temp);}return result;}bool isCvtable(string str1,string str2){//cout<<"isCvtable: "<<str1<<str2<<endl;if(str1.length()!=str2.length()){return false;}int count=0;for(int i = 0;i<str1.length();++i){if(str1[i]!=str2[i])count++;if(count>1)return false;}return count==1;}void output(map<string,vector<string> >&path,string start,string end,vector<vector<string> >&result,vector<string> & temp){temp.push_back(start);if(start==end){result.push_back(temp);return;}vector<string>::iterator iter_v;for(iter_v=path[start].begin();iter_v!=path[start].end();++iter_v){output(path,*iter_v,end,result,temp);temp.pop_back();}}};
提交online judge之后,小数据集没问题,大数据集却TLE了,分析了一下,主要是从curStep求nextStep的过程太耗时,我这个是O(N2)的时间复杂度,结果如下:
挂掉的这个案例大概有3000个词,很大,分析了一下,题目给的参数是unordered_set是有用意的,unordered_set实际底层是个hash表,所以能够常数时间索引一个字符串,基于这个思路,在已知curStep、rightside求nextStep的过程中:
对每一个curStep中的字符串,假设长度为M,那么它的每位有25种变化,也就是每个单词有25*M中变化,那么时间复杂度就变成了O(MN),单词长度一般不会太大,所以这个是个线性的算法,分析完毕,我开始着手写算法:
class Solution {public:vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) {// end typing your C/C++ solution below// DO NOT write int main() function//areslipan@163.commap<string,vector<string> > path;unordered_set<string>rightside=dict;rightside.erase(start);unordered_set<string>curStep;unordered_set<string>nextStep;curStep.insert(start);while(curStep.find(end)==curStep.end()&&!rightside.empty()){unordered_set<string>::iterator iter_us_cur;for(iter_us_cur=curStep.begin();iter_us_cur!=curStep.end();++iter_us_cur){string temp;for(int i=0;i<(*iter_us_cur).length();++i){for(int j = 0;j<26;j++){temp = *iter_us_cur;if(temp[i]!=('a'+j)){temp[i] = ('a'+j);}if(rightside.count(temp)==1){nextStep.insert(temp);if(path.find(*iter_us_cur)==path.end()){vector<string> emptyV;path.insert(make_pair(*iter_us_cur,emptyV));}path[*iter_us_cur].push_back(temp);}}}}if(nextStep.empty())break;unordered_set<string>::iterator iter_set;for(iter_set=nextStep.begin();iter_set!=nextStep.end();++iter_set){rightside.erase(*iter_set);}curStep = nextStep;nextStep.clear();}vector<vector<string> > result;vector<string> temp;if(curStep.find(end)!=curStep.end()){output(path,start,end,result,temp);}return result;}void output(map<string,vector<string> >&path,string start,string end,vector<vector<string> >&result,vector<string> & temp){temp.push_back(start);if(start==end){result.push_back(temp);return;}vector<string>::iterator iter_v;for(iter_v=path[start].begin();iter_v!=path[start].end();++iter_v){output(path,*iter_v,end,result,temp);temp.pop_back();}}};
结果出来的一瞬间很美妙:
另外,输出结果的方式也有改进的余地,如图所示,程序中的path实际是这么一张图,实际就是一张邻接表。
我的算法是从start开始深度搜索,直至找到end,当搜索到的最后一个节点不是end的时候其实都是无效搜索(而且比重很大),所以可以把上述这幅图反过来,然后从end开始反向搜索,以空间换时间。
leetcode—word ladder II的更多相关文章
- [leetcode]Word Ladder II @ Python
[leetcode]Word Ladder II @ Python 原题地址:http://oj.leetcode.com/problems/word-ladder-ii/ 参考文献:http://b ...
- LeetCode :Word Ladder II My Solution
Word Ladder II Total Accepted: 11755 Total Submissions: 102776My Submissions Given two words (start ...
- LeetCode: Word Ladder II 解题报告
Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation s ...
- [LeetCode] Word Ladder II 词语阶梯之二
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...
- LeetCode: Word Ladder II [127]
[题目] Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) ...
- [LeetCode] Word Ladder II
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...
- LeetCode:Word Ladder I II
其他LeetCode题目欢迎访问:LeetCode结题报告索引 LeetCode:Word Ladder Given two words (start and end), and a dictiona ...
- [Leetcode Week5]Word Ladder II
Word Ladder II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder-ii/description/ Descripti ...
- 【leetcode】Word Ladder II
Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation ...
随机推荐
- 团体程序设计天梯赛-练习集L2-008. 最长对称子串
L2-008. 最长对称子串 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 对给定的字符串,本题要求你输出最长对称子串的长度. ...
- sublime 配置
Sublime Text 2是那种让人会一眼就爱上的编辑器,不仅GUI让人眼前一亮,功能更是没的说,拓展性目前来说也完全够用了,网上介绍软件的文章和推荐插件的文章也不少,而且很不错,大家可以去找找自己 ...
- Get请求携带数据量的各种限制及解决办法、Post请求说明
1. Get请求携带数据量的各种限制及解决办法 Http Get方法提交的数据大小长度并没有限制,HTTP协议规范没有对URL长度进行限制.这个限制是特定的浏览器及服务器对它的限制. 到新公司处理 ...
- Git教程之远程仓库(9)
有个叫GitHub的神奇的网站,呵呵,从名字就可以看出,这个网站就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库. 由于本地Git仓库和GitHub仓库之 ...
- 转XMLHelper
http://www.cnblogs.com/lixyvip/archive/2009/09/16/1567929.html using System; using System.Collection ...
- VS2010调试 --指南 Reference from : http://blog.csdn.net/kingzone_2008/article/details/8133048
1 导言 在软件开发周期中,测试和修正缺陷(defect,defect与bug的区别:Bug是缺陷的一种表现形式,而一个缺陷是可以引起多种Bug的) 的时间远多于写代码的时间.通常,debug是指发现 ...
- 【HDOJ】2242 考研路茫茫——空调教室
tarjan缩点,然后树形dp一下可解.重点是重边的处理. /* 2242 */ #include <iostream> #include <sstream> #include ...
- Android开发之隐式Intent中Intent-filter的三个属性-action,category,data
使用隐式Intent时,需要使用到意图过滤器Intent-filter.Intent-filter含有三个属性:action,category,data.通过这三个属性的组合,可以启动想要启动的act ...
- 三个入侵的必备小工具-lcx.exe、nc.exe、sc.exe
lcx.exe的使用方法 以前抓肉鸡都是通过1433弱口令,然后.. 但是发现很多服务器开了1433,3389,但是终端是连不上的,因为服务器本身是在内网,只对外开放了1433端口,幸好有lcx. ...
- poj 1035 Spell checker(水题)
题目:http://poj.org/problem?id=1035 还是暴搜 #include <iostream> #include<cstdio> #include< ...


