126. 单词接龙 II

https://leetcode-cn.com/problems/word-ladder-ii/

解法一:dfs+bfs

import queue
class Solution:
    def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
        self.res = []  #全局变量,记录输出
        nodeNeighbors = {}  #map,k为结点名,v为结点的所有邻居名
        dict = set(wordList)  #存储所有结点名
        distances = {}  #map,k为结点名,v为起点到该节点的距离
        solution = []  #dfs辅助变量,暂存路径,用于回溯
        
        dict.add(beginWord)
        #把每个单词看做一个结点,先用一遍bfs遍历建立图结构,得到所有结点的相邻结点信息nodeNeighbors,并得到从起点到终点的最短距离
        self.bfs(beginWord, endWord, dict, nodeNeighbors, distances)
        #再用一遍dfs回溯输出所有从起点到终点的最短路径
        self.dfs(beginWord, endWord, dict, nodeNeighbors, distances, solution)

        return self.res
    
    #广度优先搜索,一层一层向外访问(类似二叉树层序)
    def bfs(self, start, end, dict, nodeNeighbors, distances):
        for d in dict:
            nodeNeighbors[d] = []
       #初始化         
        q = queue.Queue()
        q.put(start)
        distances[start] = 0
        
        while not q.empty():
            count = q.qsize()  #该层规模
            foundEnd = False  #标志位,该层是否能到达终点
            
            for i in range(count):  #遍历该层所有结点
                cur = q.get()
                neighbors = self.getNeighbors(cur, dict)
                print(i, cur , neighbors)
                print(nodeNeighbors[cur])
                for neighbor in neighbors:
                    nodeNeighbors[cur].append(neighbor)
                    if neighbor not in distances:  #避免重复访问
                        distances[neighbor] = distances[cur] + 1
                        if neighbor == end:  #到达终点
                            foundEnd = True
                        else:
                            q.put(neighbor)
            if foundEnd:  #若该层能到达终点,则不再访问下一层(求最短距离)
                break
   
   #求某个结点的所有相邻结点     
    def getNeighbors(self, nodeString, dict):
        res = []
        chs = list(nodeString)
        #对每个字符,分别将其替换成另外的25个字符
        for i in range(len(chs)):
            for ch in 'abcdefghijklmnopqrstuvwxyz':
                if ch == chs[i]:  #跳过原字符,换成其他字符
                    continue
                tmp = chs[i]  #暂存原字符
                chs[i] = ch  #替换
                newString = "".join(chs)
                if newString in dict:  #找到在wordList中的字符串
                    res.append(newString)
                chs[i] = tmp  #还原
        return res                      
                    
   #深度优先遍历,回溯输出所有最短路径,solution暂存当前路径         
    def dfs(self, cur, end, dict, nodeNeighbors, distances, solution):
        solution.append(cur)  #尝试写入当前节点
        if cur == end:  #若能到达终点,将当前路径复制加入全局res
            self.res.append(list(solution))
        #对当前节点的所有邻居
        for next in nodeNeighbors[cur]:
         	#关键,保证向下一级访问(不回头)
            if distances[next] == distances[cur] + 1:
                self.dfs(next, end, dict, nodeNeighbors, distances, solution)
        solution.pop()  #弹出当前节点

最后更新于