單詞接龍 II
思路①:
(圖示別人的 )
單純用DFS求路徑也是可行的,但是冗餘搜索太多。
其中一條造成冗餘的原因:每當一個節點向它同一層的節點向前搜索時,那麼它下面走的所有的路徑都不可能是我們要求的最短路徑。
基於這個想法,我的優化想法也很簡單,就是在BFS時記錄下每一層的節點,然後DFS時只去某個節點的下一層去建立搜索關係,這樣就避免了走彎路。
時間一般。
class Solution {
public:
unordered_set<string> wordSet;
unordered_set<string> vis;
unordered_map<int,unordered_set<string>> nodesInLayer;
vector<vector<string>> ans;
int layer = 1;
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
for(string s:wordList){
wordSet.insert(s);
}
if(!wordSet.count(endWord)){
return ans;
}
bfs(beginWord,endWord);
// cout<<layer<<endl;
nodesInLayer[layer].insert(endWord);
vector<string> list;
dfs(beginWord,endWord,list,0);
return ans;
}
void dfs(string beginWord,string &endWord,vector<string> &list,int depth){
list.push_back(beginWord);
if(beginWord==endWord){
ans.push_back(list);
return;
}
for(int i=0;i<beginWord.size();i++) {
char origin = beginWord[i];
for(char c='a';c<='z';c++){
if(c==origin){
continue;
}
beginWord[i] = c;
if(nodesInLayer[depth+1].count(beginWord)){
// cout<<"--"<<beginWord<<endl;
dfs(beginWord,endWord,list,depth+1);
list.pop_back();
}
beginWord[i] = origin;
}
}
}
void bfs(string beginWord,string endWord){
queue<string> q;
q.push(beginWord);
vis.insert(beginWord);
while(!q.empty()){
int size = q.size();
while(size--){
string x = q.front();
q.pop();
for(int i=0;i<x.size();i++){
char origin = x[i];
for(char c='a';c<='z';c++){
if(c==origin){
continue;
}
x[i] = c;
if(wordSet.count(x) && !vis.count(x)){
if(x==endWord){
return;
}
q.push(x);
vis.insert(x);
nodesInLayer[layer].insert(x);
// cout<<layer<<"--"<<x<<endl;
}
x[i] = origin;
}
}
}
layer++;
}
}
};
思路②:
這是一位網友的思路。
在BFS時,用unordered_map<string,unordered_set<string>> nextMap
去記錄下某個節點的所有後繼節點。
不過這個處理方法在寫BFS時有個坑點:
如下圖的實例2,只能在搜索完一整層的節點之後,才能將由這一層拓展出來的節點標記,否則就會缺少必要的連接。
一個這個unordered_map<string,unordered_set<string>> nextMap
構建好,DFS求路徑反而倒簡單多了。
class Solution {
public:
unordered_set<string> wordSet;
unordered_set<string> vis;
unordered_map<string,unordered_set<string>> nextMap;
int lenOfSequence = 0;
vector<vector<string>> ans;
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
bfs(beginWord,endWord,wordList);
vector<string> list;
dfs(beginWord,endWord,list);
return ans;
}
void dfs(const string &x,string &endWord,vector<string> &list){
list.push_back(x);
if(x==endWord){
ans.push_back(list);
return;
}
unordered_set<string> &set = nextMap[x];
for(unordered_set<string>::iterator it = set.begin();it!=set.end();it++){
dfs(*it,endWord,list);
list.pop_back();
}
}
void bfs(string beginWord, string endWord, vector<string>& wordList) {
for(string&s:wordList){
wordSet.insert(s);
}
if(!wordSet.count(endWord)){
return ;
}
queue<string> q;
q.push(beginWord);
vis.insert(beginWord);
int step = 1;
while(!q.empty()){
int size = q.size();
vector<string> temp;
while(size--){
string a = q.front();
string origin_a = a;
q.pop();
//時間複雜度 26*wordLen
for(int i=0;i<a.size();i++){
char origin = a[i];
for(char c = 'a';c<='z';c++){
if(c==origin){
continue;
}
a[i] = c;
if(wordSet.count(a) && !vis.count(a)){
if(a==endWord){
if(lenOfSequence==0){
lenOfSequence = step+1;
}else if(lenOfSequence<step+1){
continue;
}
}
if(a!=endWord)
{
q.push(a);
temp.push_back(a);
}
nextMap[origin_a].insert(a);
}
a[i] =origin;
}
}
}
step++;
for(string& s:temp){
vis.insert(s);
}
}
}
};