LeetCode 126. 單詞接龍 II(BFS求出路徑點+DFS得出所有路徑)兩種思路

單詞接龍 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);
            }
        } 
    }

};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章