Word Ladder
2015-10-07 10:32
246 查看
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time
Each intermediate word must exist in the word list
For example,
Given:
beginWord =
endWord =
wordList =
As one shortest transformation is
return its length
Note:
Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
这里我们可以不用实际构造图,而在BFS遍历的时候去寻找当前单词可达的下一个单词。如果还是通过遍历所有的单词判断是否可达,则复杂度和上面一样,但实际上在上千个单词中,只有少数几个可以由当前单词一步到达,我们之前的比较浪费了很多时间在不可能的单词上。网上对该问题的解决无一例外都是按照下面的思路:将当前单词每一个字符替换成a~z的任意一个字符,然后判断是否在词典中出现。此时的复杂度是O(26*word_length),当单词比较短时,这种方法的优势就体现出来了。
Only one letter can be changed at a time
Each intermediate word must exist in the word list
For example,
Given:
beginWord =
"hit"
endWord =
"cog"
wordList =
["hot","dot","dog","lot","log"]
As one shortest transformation is
"hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length
5.
Note:
Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
class Solution { public: int countStep(const string& s1, const string& s2) { int len1 = s1.size(); // int len2 = s2.size(); // if(len1 != len2) // { // return 0; // } int i; int step = 0; for(i = 0; i < len1; ++i) { if(s1[i] != s2[i]) { ++step; if(step >= 2) { return step; } } } return step; } int ladderLength(string beginWord, string endWord, unordered_set<string>& wordList) { unordered_set<string>::iterator it = wordList.begin(); unordered_set<string> del; queue<string> Q1; queue<string> Q2; int count = 0; if(beginWord == endWord) { return count; } for(; it != wordList.end(); ++it) { if(countStep(*it, beginWord) == 1) { Q1.push(*it); //itmp //wordList.erase(*it); }else { del.insert(*it); } } ++count; wordList.clear(); while(1) { while(!Q1.empty()) { if(countStep(Q1.front(), endWord) == 0) { //++count; return count; }else if(countStep(Q1.front(), endWord) == 1) { ++count; return count; }else { for(it = del.begin(); it != del.end(); ++it) { if(countStep(*it, Q1.front()) == 1) { Q2.push(*it); }else { wordList.insert(*it); } } //wordList.erase(Q1.front()); Q1.pop(); } } del.clear(); if(wordList.size() == 0) { return 0; } if(Q1.empty() && Q2.empty()) { return 0; //break; } ++count; while(!Q2.empty()) { if(countStep(Q2.front(), endWord) == 0) { //++count; return count; }else if(countStep(Q2.front(), endWord) == 1) { ++count; return count; }else { for(it = wordList.begin(); it != wordList.end(); ++it) { if(countStep(*it, Q2.front()) == 1) { Q1.push(*it); }else { del.insert(*it); } } //wordList.erase(Q2.front()); Q2.pop(); } } wordList.clear(); if(del.size() == 0) { return 0; } if(Q1.empty() && Q2.empty()) { return 0; //break; } ++count; } return count; } };上面这段代码一直超时,原因在于 构造图的每一层时的时间复杂度是 n^2级别
这里我们可以不用实际构造图,而在BFS遍历的时候去寻找当前单词可达的下一个单词。如果还是通过遍历所有的单词判断是否可达,则复杂度和上面一样,但实际上在上千个单词中,只有少数几个可以由当前单词一步到达,我们之前的比较浪费了很多时间在不可能的单词上。网上对该问题的解决无一例外都是按照下面的思路:将当前单词每一个字符替换成a~z的任意一个字符,然后判断是否在词典中出现。此时的复杂度是O(26*word_length),当单词比较短时,这种方法的优势就体现出来了。
class Solution { public: int ladderLength(string start, string end, unordered_set<string> &dict) { // IMPORTANT: Please reset any member data you declared, as // the same Solution instance will be reused for each test case. //BFS遍历找到的第一个匹配就是最短转换,空字符串是层与层之间的分隔标志 queue<string> Q; Q.push(start); Q.push(""); int res = 1; while(Q.empty() == false) { string str = Q.front(); Q.pop(); if(str != "") { int strLen = str.length(); for(int i = 0; i < strLen; i++) { char tmp = str[i]; for(char c = 'a'; c <= 'z'; c++) { if(c == tmp)continue; str[i] = c; if(str == end)return res+1; if(dict.find(str) != dict.end()) { Q.push(str); dict.erase(str); } } str[i] = tmp; } } else if(Q.empty() == false) {//到达当前层的结尾,并且不是最后一层的结尾 res++; Q.push(""); } } return 0; } };
相关文章推荐
- 最长不上升(下降)子序列——拦截导弹
- [Search Engine] 搜索引擎技术之查询处理
- (转)vim命令集
- 面试问题1
- C# lambda表达式
- 《剑指Offer》面试题:判读数组是否是某二叉搜索树的后序遍历
- matlab中的文本处理
- 实验室阶段性小结2
- RHCSA 系列(十五): 虚拟化基础和使用 KVM 进行虚拟机管理
- Word Pattern
- 实验室阶段性小结1
- iOS开发中一些小知识
- 深入Java集合学习系列:WeakHashMap的实现原理
- win7 64位启动virtualBox虚拟机的失败案例一 VBoxDD.dll
- Hibernate 3.2 与MySQL 5.6插入中文乱码问题
- 面试技巧
- 【Python】Learn Python the hard way, ex10 转义字符
- C++ operator关键字(重载操作符)
- 深入Java集合学习系列:Hashtable的实现原理
- Mysql的安装及的完全卸载