您的位置:首页 > 其它

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 = 
"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;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: