思路:参考http://www.cnblogs.com/grandyang/p/4548184.html
代码中的每一步都按我自己的理解进行注释了。
class Solution {
public:
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
//ans存放最后结果
vector<vector<string> > ans;
//防止原始数据被破坏,将原始数据复制一遍,并且可以去除掉已经循环了的词
unordered_set<string> dict(wordList.begin(),wordList.end());
//记录已经循环过的词
vector<string> p{beginWord};
//存放动态的路径,这里不一定是满足条件的路径,这样可以一直去除最后一个词进行比较
queue<vector<string> > paths;
//指定路径的开头
paths.push(p);
//存放已经循环过的单词。
unordered_set<string> words;
//分别记录当前路径的长度,和最小路径长度。
int level=1,minlength=INT_MAX;
while(!paths.empty())
{
//paths中会不断的推入一些动态路径,逐个取出,添加新的单词。
vector<string> t=paths.front();paths.pop();
//如果t的长度大于level,则表示有些单词已经循环过了,不必再次循环了,去除这些单词,可以达到剪枝的效果。
if(t.size()>level)
{
for(string s:words) dict.erase(s);
words.clear();
level=t.size();
if(level>minlength) break;
}
//取出路径中的最后一个单词。
string last=t.back();
for(int i=0;i<last.size();++i)
{
string newlast=last;
//逐步替换newlast中的一个单词,并判断newlast是否在字典dict中。不存在则continue,直到找到一个存在的,或者循环结束。
for(char ch='a';ch<='z';++ch)
{
newlast[i]=ch;
if(!dict.count(newlast)) continue;
//将已经循环过的单词存入words中,下一次执行while循环的时候,就会把这个单词从dict中删除。
words.insert(newlast);
vector<string> nextpath=t;
//更新一个新的路径
nextpath.push_back(newlast);
if(newlast==endWord)
{
ans.push_back(nextpath);
minlength=level;
}
else
{
paths.push(nextpath);
}
}
}
}
return ans;
}
};