和上一个单词接龙不一样在,这道题返回所有的最短路径
记录搜索路径的宽搜:
1.将普通队列更换为vector,保存所有的搜索结点,在pop时不会丢弃队头元素,只是移动front指针
2.在队列结点中增加该结点的前驱结点在队列中的下标信息,可通过该下标找到是从队列中的哪个结点搜索到当前结点的
多条路径的保存:
到达某一位置可能存在多条路径,使用映射记录到达每个位置的最短需要步数,新拓展到的位置只要未曾到达或到达步数与最短步数相同,即将该位置添加到队列中,从而存储了从不同前驱到达该位置的情况
struct item{
string node;
int pre_pos;
int step;
item(string _node,int _pre_pos,int _step):node(_node),pre_pos(_pre_pos),step(_step){}
};
class Solution {
public:
bool connect(string& s1,string& s2)
{
int cnt = 0;
for(int i =0;i<s1.size();++i)
{
if(s1[i]!=s2[i])
cnt++;
}
return cnt == 1;
}
//构建图与单词接龙1有一些不一样,因为上一题是求出最短步数就行,而这一题需要求出所有的最短路径
//如果wordlist里面有了beginword,我们又push了一个beginword进去,就会有重复路径
void construct_graph(string& beginword,vector<string>& wordlist,map<string,vector<string> >& graph)
{
int has_beginword = 0;
for(int i =0;i<wordlist.size();++i)
{
if(wordlist[i] == beginword)
has_beginword = 1;
graph[wordlist[i]] = vector<string>();
}
for(int i =0;i<wordlist.size();++i)
{
for(int j = i+1;j<wordlist.size();++j)
{
if(connect(wordlist[i],wordlist[j]))
{
graph[wordlist[i]].push_back(wordlist[j]);
graph[wordlist[j]].push_back(wordlist[i]);
}
}
if(has_beginword == 0 && connect(wordlist[i],beginword))
{
graph[wordlist[i]].push_back(beginword);
graph[beginword].push_back(wordlist[i]);
}
}
}
//队列, 终点单词所在队列的位置下标
void BFS(string& beginword,string& endword,map<string,vector<string> >& graph,vector<item>& q,vector<int>& end_word_pos)
{
map<string,int> visit;//<单词,步数>
int min_step = 0;
q.push_back(item(beginword,-1,1));//起始单词的前驱为-1
visit[beginword] = 1;
int front = 0;//队列头指针
while(front != q.size())
{
string node = q[front].node;
int step = q[front].step;
if(min_step != 0 && step > min_step)//step > min_step代表所有到终点的路径都搜索完成
break;
if(node == endword)
{
min_step = step;//搜索到结果时,记录到达终点
end_word_pos.push_back(front);
}
vector<string> neighbors = graph[node];
for(int i =0;i<neighbors.size();++i)
{ //结点没被访问,或是另一条最短路径
if(visit.find(neighbors[i]) == visit.end() || visit[neighbors[i]] == step+1)
{
q.push_back(item(neighbors[i],front,step+1));
visit[neighbors[i]] = step + 1;
}
}
front++;
}
}
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
map<string,vector<string> > graph;
vector<item> q;
vector<int> end_word_pos;
construct_graph(beginWord,wordList,graph);
BFS(beginWord,endWord,graph,q,end_word_pos);
vector<vector<string> > res;
//保存路径结果
for(int i = 0;i<end_word_pos.size();++i)
{
int pos = end_word_pos[i];
vector<string> path;//从后向前保存路径,之后再反过来存入到res中
while(pos != -1)
{
path.push_back(q[pos].node);
pos = q[pos].pre_pos;
}
res.push_back(vector<string>());
for(int j = path.size() -1 ;j>=0;--j)
res[i].push_back(path[j]);
}
return res;
}
};