单词与单词之间的转换,可以理解为一张图,图的顶点是单词,若两单词之间可以互相转换,则这两个单词所代表的顶点间有一条边,求图中结点beginword到endWord的所有路径中,最少包括多少个结点。图的宽度优先搜索
使用map构造邻接表表示的图,map<string,vector<string> >,遍历wordList,对任意两个单词,若wordList[i],wordList[j]只相差一个字符,则将其相连。
建了图之后进行图的宽度遍历
给定图的起点beginword,终点endword,图graph,从begin开始搜索,搜索过程记录步数
1.设置搜索队列Q,队列结点为pair<顶点,步数>,设置集合visit,记录搜索过的顶点,将<beginword,1>添加到队列
2.队列不空,取出头部元素:
若取出的元素是endword,返回到达当前结点的步数
否则拓展该结点,将与该节点相邻的且未添加到visit的结点与步数push到Q,并将这个顶点加入visit
3.最终无法搜索到endword,返回0
class Solution {
public:
//检查这两个单词是不是相差一个字符的
bool connect(const string& word1, const string& word2)
{
int cnt =0;
for(int i = 0;i<word1.size();++i)
{
if(word1[i]!=word2[i])
cnt++;
}
return cnt == 1;
}
//构造图
void construct_graph(string& beginword,vector<string>& wordlist,map<string,vector<string> >& graph)
{
wordlist.push_back(beginword);
for(int i =0;i<wordlist.size();++i)
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]);
}
}
}
}
//宽度搜索图
int BFS(string& beginword,string& endword,map<string,vector<string> >& graph)
{
queue<pair<string, int>>q;//搜索队列 <顶点,步数>
set<string> visit;//记录已访问的顶点
q.push(make_pair(beginword,1));
visit.insert(beginword);
while(!q.empty())
{
string node = q.front().first;
int step = q.front().second;
q.pop();
if(node == endword)
return step;
vector<string> neighbors = graph[node];//取node的邻接点
for(int i = 0;i<neighbors.size();++i)
{
if(visit.find(neighbors[i]) == visit.end())
{
q.push(make_pair(neighbors[i],step+1));
visit.insert(neighbors[i]);
}
}
}
return 0;
}
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
map<string,vector<string> > graph;
construct_graph(beginWord,wordList,graph);
return BFS(beginWord,endWord,graph);
}
};