leetcode126. 单词接龙 II

题目:

给定两个单词(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” 不在字典中,所以不存在符合要求的转换序列。

思路:先广搜再深搜。

 首先,直接深搜回溯是可以得到答案的,但这样会超时。而广搜可以直接找到最短路径,这样就可以停止搜索。同时题目要求输出最短的路径,因此在广搜的过程中,我们需要记录路径信息。
 在广搜之前,我们实现一个getNextWords()函数,用来获取单词在字典中可以转换的单词,也就是该单词的下一层可能出现的单词。同时,为了避免重复访问相同的单词,我们用一个集合visited来记录已经访问过的单词。建立一个邻接表table,记录每个单词在广搜的过程中实际可以到达的单词,即路径信息,这里用字典来存储。这些工作做好后,开始广搜:

beginWord入队列,同时加入visited集合。
若队列不为空:

  • 取出当前队列所有节点,加入visited集合;
  • visited集合出现endWord,结束程序,返回得到的邻接表;
  • 对每一个节点,调用getNextWords()函数得到转换单词,若转换单词没有在visited集合,则加入队列,同时加入节点的邻接表。

BFS的实现过程需要注意,能用set()绝不用list(),在提交的过程中这个思路用list超时过不了!!!

广搜结束后得到邻接表,对该邻接表回溯深搜,即可得到最短路径。举例如下:

在这里插入图片描述
代码:

class Solution:
    def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:

        def getNextWords(curWord, wordSet):
            res = set()
            for i in range(len(curWord)):
                for j in string.ascii_lowercase:
                    s = curWord[0:i] + j + curWord[i + 1:len(curWord)]
                    if s == curWord or s not in wordSet:
                        continue
                    res.add(s)
            return res

        def bfs(beginWord, visited, wordSet):
            queue = []
            queue.append(beginWord)
            table = {}
            found = False
            while queue:
                l = len(queue)
                for i in queue:
                    visited.add(i)
                
                for i in range(l):
                    cur = queue.pop(0)
                    curNext = set()
                    for j in iter(getNextWords(cur, wordSet)):
                        if j in visited:
                            continue
                        queue.append(j)
                        curNext.add(j)
                        if j == endWord:
                            found = True

                    table[cur] = curNext
                if found :
                    break
            return table

        def dfs(curWord, endWord, table, path, res):
            if curWord == endWord:
                res.append(path[:])
                return
            if curWord not in table.keys():
                return
            for nextWord in table[curWord]:
                path.append(nextWord)
                dfs(nextWord, endWord, table, path, res)
                path.pop()

        wordSet = set(wordList)
        if endWord not in wordSet:
            return []
        visited = set()
        table = bfs(beginWord, visited, wordSet)
        res = []
        dfs(beginWord, endWord, table, [beginWord], res)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值