(1) Word Ladder I
BFS(宽度优先搜索),但是我们可以假想构建一个图,其中图中的每个顶点都是我们的元素,点和点是如何联系起来的呢?如果一个单词通过改变一次字母,能够变成另外一个单词,我们称之为1 edit distance 距离(是不是想起了leetcode中edit distance那道题目了?)所以,图中的所有相邻元素都是edit distance 距离为1的元素。那么,我们只需要做BFS,哪里最先遇到我们的target word,那么我们的距离就是多少。如果遍历完所有的元素都没有找到target word,那么我们就返回1。[1]
class Solution {
public:
int ladderLength(string start, string end, unordered_set<string> &dict) {
if(start==end)
return 1;
queue<string> neighbor,curque;
int distance=1;
curque.push(start);
while(dict.size()>0 && !curque.empty())
{
while(!curque.empty())
{
string cur(curque.front());
curque.pop();
for(int i=0;i<start.size();i++)
for(char j='a';j<='z';j++)
{
string tmp(cur);
tmp[i]=j;
if(tmp==end)
return distance+1;
if(dict.count(tmp)>0)
{
neighbor.push(tmp);
dict.erase(tmp);
}
}
}
distance++;
swap(neighbor,curque);
}
return 0;
}
};
(2) Word Ladder II
使用了一个前驱单词表,即记录每一个单词的前驱单词是哪些。这样先bfs遍历完毕后,我们从end出发dfs递归就能把所有路径生成出来。[2]
class Solution {
private:
vector<vector<string>> ret;
bool bfs(string start,string end,unordered_map<string, vector<string>> &premap,unordered_set<string> &dict) {
for(auto iter = dict.begin(); iter != dict.end(); ++iter)
premap[*iter] = vector<string>();
vector<unordered_set<string>> candidates(2);
int current = 0;
int previous = 1;
candidates[current].insert(start);
while(true)
{
current = !current;
previous = !previous;
for (auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter)
dict.erase(*iter);
candidates[current].clear();
for(auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter)
{
for(int i=0;i<start.size();i++)
{
string tmp(*iter);
for(char j='a';j<='z';j++)
{
if(tmp[i]==j)
continue;
tmp[i]=j;
if(dict.count(tmp)>0)
{
if(candidates[current].count(tmp)==0)
candidates[current].insert(tmp);
premap[tmp].push_back(*iter);
}
}
}
}
if (candidates[current].size() == 0)
return true;
if (candidates[current].count(end)) break;
}
return false;
}
void dfs(string &cur,vector<string> &tmp,unordered_map<string, vector<string>> &premap) {
if(premap[cur].size()==0)
{
tmp.push_back(cur);
vector<string> curPath = tmp;
reverse(curPath.begin(),curPath.end());
ret.push_back(curPath);
tmp.pop_back();
return;
}
tmp.push_back(cur);
for(auto iter=premap[cur].begin();iter != premap[cur].end(); iter++)
dfs(*iter,tmp,premap);
tmp.pop_back();
}
public:
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
ret.clear();
unordered_map<string, vector<string>> premap;
if(bfs(start,end,premap,dict))
return ret;
vector<string> tmp;
dfs(end,tmp,premap);
return ret;
}
};
注意参数尽可能用引用传值,不然递归的时候可能会内存溢出。
参考:
[1] http://blog.csdn.net/zxzxy1988/article/details/8591890
[2] http://blog.csdn.net/doc_sgl/article/details/13341405