LeetCode - 解题笔记 - 126 - Word Ladder II

Solution 1

本体要求最小路径,因此BFS没跑,但是要求递归所有最小结果,可能还是需要DFS的,但是当前版本的实现不需要DFS。利用前几个题的分层BFS,以路径为节点可以完成搜索。使用哈希表来优化存在判定的时间。

此外,一个题解中使用了双向BFS来优化搜索空间,整个思路就是交替地从两个单词展开并找到相遇的时刻,此时刻下相遇位置各自搜索路径的结合即为最优方案:详细通俗的思路分析,多解法 - 单词接龙 II - 力扣(LeetCode) (leetcode-cn.com)

我的实现慢的有点过分,但是目前以学习为主,优化留给后面

  • 时间复杂度: O ( N d ) O(N^d) O(Nd),其中 N N N为wordList的长度, d d d为编辑距离,最坏的搜索范围就是每一层都是全展开,实际会有大量剪枝
  • 空间复杂度: O ( d N d ) O(dN^d) O(dNd),其中 N N N为wordList的长度, d d d为编辑距离,最坏的搜索范围就是每一层都是全展开,保存的是路径,因此最后一层的每个节点大小都应为 d d d,实际会有大量剪枝
class Solution {
public:
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        
        vector<vector<string>> ans;
        
        // 序列中必须要有endWord
        unordered_set<string> words = {wordList.begin(), wordList.end()};
        if (words.find(endWord) == words.end()) {
            return ans;
        }
        
        this->bfs(beginWord, endWord, words, ans);
            
        return ans;
    }
    
private:
    void bfs(string & beginWord, string & endWord, unordered_set<string> & words, vector<vector<string>> & ans) {
        
        queue<vector<string>> q;
        vector<string> path;
        path.push_back(beginWord);
        q.push(path);
        
        bool flag = false; // 是否向下层搜索
        unordered_set<string> visited;
        
        while (!q.empty()) {
            // 分层bfs
            int size = q.size();
            vector<string> tempVisited; 
            while (size--) {
                auto temp = q.front();
                q.pop();
                auto tempWord = temp.back();
                
                auto mods = this->getMods(tempWord, words);
                for (auto mod: mods) {
                    if (visited.find(mod) == visited.end()) {
                        // 得是之前没出现过的单词
                        temp.push_back(mod);
                        if (mod == endWord) {
                            // 正好找到endWord,搜索完当前层后终止
                            flag = true;
                            ans.push_back(temp);
                        } else {
                            // 不是,保存结果路径到队列中
                            q.push(temp);
                            tempVisited.push_back(mod);
                        }
                        temp.pop_back();
                        
                    }
                }
            }
            
            if (flag) { break; }
            
            visited.insert(tempVisited.begin(), tempVisited.end());
        }
    }
    
    
    vector<string> getMods (string word, unordered_set<string> & words) {
        vector<string> mods;
        
        for (int index = 0; index < word.size(); ++index) {
            auto temp = word[index];
            for (char ch = 'a'; ch <= 'z'; ++ch) {
                
                if (temp != ch) {
                    word[index] = ch;
                    if (words.find(word) != words.end()) {
                        mods.push_back(word);
                    }
                }
    
            }
            word[index] = temp;
        }
        
        return mods;
    }
};

Solution 2

Solution 1的Python实现

class Solution:
    def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
        
        
        def bfs() -> None :
            nonlocal beginWord, endWord, wordList, ans
            
            q = deque()
            path = list()
            path.append(beginWord)
            q.append(path)
            
            flag = False
            visited = set()
            
            while len(q) > 0:
                size = len(q)
                
                tempVisited = list()
                
                while size > 0:
                    temp = q.popleft()
                    tempWord = temp[-1]
                    
                    mods = getMods(tempWord)
                    for mod in mods:
                        if mod not in visited:
                            temp.append(mod)
                            if mod == endWord:
                                flag = True
                                ans.append(copy.deepcopy(temp))
                            else:
                                q.append(copy.deepcopy(temp))
                                tempVisited.append(mod)
                                
                            temp.pop()
                    
                    size -= 1
                
                if flag: break
                    
                visited.update(tempVisited)
            
        def getMods(word: str) -> List[str]:
            nonlocal wordList
            
            mods = list()
            word_list = list(word)
            for i in range(len(word)):
                temp = word_list[i]
                for ch in string.ascii_lowercase:
                    word_list[i] = ch
                    newWord = ''.join(word_list)
                    if newWord in wordList:
                        mods.append(newWord)
                        
                
                word_list[i] = temp
                
            return mods
        
        
        ans = list()
        
        if endWord not in wordList: return ans
        
        bfs()
        
        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值