Leetcode-126.单词接龙2
给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回一个空列表。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:
输入:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
输出:
[
[“hit”,“hot”,“dot”,“dog”,“cog”],
[“hit”,“hot”,“lot”,“log”,“cog”]
]
示例 2:
输入:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
输出: []
解释: endWord “cog” 不在字典中,所以不存在符合要求的转换序列。
思路:
1.构建结点之间的图关系,把一个个字符串作为结点,然后经过一次变换能得到的字符串作为邻接结点,(注意:一定要考虑给定的字符串中是否包含了开始结点)
用unordered_map<string, vector > graph实现
2.用vector all_node最为队列记录关系,其中node中包含该字符串,以及字串变换来的前驱节点和现在的变换的次数,用unordered_map记录该节点最早出现的次数,在之后要是遍历到该结点,若是出现过并且步数超过记录的,则不用管。
3.先把开始结点放入all_node,并且不断遍历其邻接结点。判断结点,是否是最后的结点,若是则判断其是否超过第一次出现的时候的步长(需记录最后一个结点第一次出现的步长),若超过则直接停止循环,若没有,把记录最后结点的位置(用数组记录最后结点的位置)。判断邻接结点若没有出现过,则加入all_node,并记录其前驱和步长,若出现过判断是否是刚出现过还是之前出现过,若是之前出现过,则该节点不用管。
代码:
class Solution {
public:
struct node{
string s;
int left;
int step;
node(string s, int left, int step):s(s), left(left), step(step){}
};
bool connect(string &Word1, string &Word2){
int count = 0;
for(int i = 0; i < Word2.size(); i++){
if(Word1[i] != Word2[i]){
count++;
}
}
return count == 1;
}
void construct_graph(string &beginWord, unordered_map<string, vector<string> > &graph, vector<string>& wordList){
int flag = 0;
for(int i = 0; i < wordList.size(); i++){
graph[wordList[i]] = vector<string>();
if(beginWord == wordList[i]){
flag = 1;
}
}
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(flag == 0 && connect(beginWord, wordList[i])){
graph[beginWord].push_back(wordList[i]);
}
}
}
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
unordered_map<string, vector<string> > graph;
construct_graph(beginWord, graph, wordList);
vector<node> all_node;
unordered_map<string, int> nodes_step;
all_node.push_back(node(beginWord, -1, 1));
nodes_step[beginWord] = 1;
int begin = 0;
int min_step = 0;
vector<int> end_node_id;
while(begin < all_node.size()){
string s_temp = all_node[begin].s;
int step_temp = all_node[begin].step;
if(min_step != 0 && step_temp > min_step){
break;
}
if(s_temp == endWord){
min_step = step_temp;
end_node_id.push_back(begin);
}
vector<string> neighbors = graph[s_temp];
for(int i = 0; i < neighbors.size(); i++){
if(nodes_step.find(neighbors[i]) == nodes_step.end() || nodes_step[neighbors[i]] == step_temp+1){
all_node.push_back(node(neighbors[i], begin, step_temp+1));
nodes_step[neighbors[i]] = step_temp + 1;
}
}
begin++;
}
vector<vector<string> > res;
for(int i = 0; i < end_node_id.size(); i++){
vector<string> res_temp;
int end_id = end_node_id[i];
while(end_id != -1){
res_temp.insert(res_temp.begin(), all_node[end_id].s);
end_id = all_node[end_id].left;
}
res.push_back(res_temp);
}
return res;
}
};