题目详情如下:
给定一个单词集合Dict,其中每个单词的长度都相同。现从此单词集合Dict 中抽取两个
单词A、B,我们希望通过若干次操作把单词A 变成单词B,每次操作可以改变单词的一个
字母,同时,新产生的单词必须是在给定的单词集合Dict 中。求所有行得通步数最少的修
改方法。
举个例子如下:
Given:
A = “hit”
B = “cog”
Dict = [“hot”,”dot”,”dog”,”lot”,”log”]
Return
[
[“hit”,”hot”,”dot”,”dog”,”cog”],
[“hit”,”hot”,”lot”,”log”,”cog”]
]
即把字符串A = “hit”转变成字符串B = “cog”,有以下两种可能:
“hit” -> “hot” -> “dot” -> “dog” -> “cog”;
“hit” -> “hot” -> “lot” -> “log” ->”cog”。

这一题相当的好,详细解析见编程艺术第32章

#include <iostream>
#include<vector>
#include<string>
#include<set>
#include <map>
#include <queue>
using namespace std;


class Solution
{
public:
// help 函数负责找到所有的路径
void help(int x,vector<int> &d, vector<string> &word,vector<vector<int> > &next,
vector<string> &path,vector<vector<string> > &answer) {
path.push_back(word[x]);
if (d[x] == 0) { //已经达到终点了
answer.push_back(path);
}
else {
int i;
for (i = 0; i <next[x].size(); ++i) {
help(next[x][i],d, word, next,path,answer);
}
}
path.pop_back(); //回溯
}
vector<vector<string>> findLadders(string start, string end, set<string>& dict)
{
vector<vector<string> > answer;
if (start == end) { //起点终点恰好相等
return answer;
}
//把起点终点加入字典的map
dict.insert(start);
dict.insert(end);
set<string>::iterator dt;
vector<string> word;
map<string,int>allword;
//把set 转换为map,这样每个单词都有编号了。
for (dt = dict.begin(); dt!= dict.end(); ++dt) {
word.push_back(*dt);
allword.insert(make_pair(*dt, allword.size()));
}
//建立连边 邻接表
vector<vector<int> > con;
int i,j,n =word.size(),temp,len = word[0].length();
con.resize(n);
for (i = 0; i < n; ++i){
for (j = 0; j <len; ++j) {
char c;
for (c =word[i][j] + 1; c <= 'z'; ++c) { //根据上面第二种方法的优化版的思路,让每个单词每个位置变更大
char last =word[i][j];
word[i][j] =c;
map<string,int>::iterator t = allword.find(word[i]);
if (t !=allword.end()) {
con[i].push_back(t->second);
con[t->second].push_back(i);
}
word[i][j] =last;
}
}
}
//以下是标准bfs 过程
queue<int> q;
vector<int> d;
d.resize(n, -1);
int from = allword[start],to = allword[end];
d[to] = 0; //d 记录的是路径长度,-1 表示没经过
q.push(to);
vector<vector<int> > next;
next.resize(n);
while (!q.empty()) {
int x = q.front(), now= d[x] + 1;
//now 相当于路径长度
//当now > d[from]时,则表示所有解都找到了
if ((d[from] >= 0)&& (now > d[from])) {
break;
}
q.pop();
for (i = 0; i <con[x].size(); ++i) {
int y = con[x][i];
//第一次经过y
if (d[y] < 0) {
d[y] = now;
q.push(y);
/************************************************************************/
/*反着bfs搜索,所以next[y].push_back(x);注意BFS求得就是最短路径
/************************************************************************/
next[y].push_back(x);
}
//非第一次经过y
else if(d[y] ==now) { //是从上一层经过的,所以要保存
next[y].push_back(x);
}
}
}

if (d[from] >= 0) { //有解
vector<string>path;
help(from, d,word,next, path,answer);
}

return answer;

}
};



int main(){

set<string> dict;
dict.insert("hot");
dict.insert("dot");
dict.insert("dog");
dict.insert("lot");
dict.insert("log");

Solution a;

vector<vector<string>> ans = a.findLadders("hit","cog",dict);

for(int i=0;i<ans.size();i++){
for(int j=0;j<ans[i].size();j++){
cout<<ans[i][j]<<" ";
}
cout<<endl;
}

system("pause");
return 0;
}

这段代码看了一个晚上和半个上午,可以说大致懂了,还有两处不是很清楚
1.else if(d[y] ==now) { //是从上一层经过的,所以要保存
next[y].push_back(x);
}

2.help()这个递归函数

究其原因还是对BFS和DFS理解不深入,打算过几天深入做几个相关的题再回头看这题。