2020-12-23

题目描述:给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:
每次转换只能改变一个字母。
转换后得到的单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回一个空列表。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
解题思路一:先利用字典里的单词以及开始和结尾单词构建一个图,如果两个单词之间只有一个字母不一样那么他们之间就会有一条边,然后通过回溯的方法找到转移的路径,构建图的过程可以用队列模拟bfs的过程,只要达到了结尾单词就可以结束循环

class Solution:
    def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
        word_dict = set(wordList)
        if endWord not in word_dict:
            return []
        if beginWord in word_dict:
            word_dict.remove(beginWord)
        from collections import defaultdict
        G = defaultdict(list)
        import queue
        q = queue.Queue()
        q.put(beginWord)
        word_dict.remove(endWord)
        found = False
        while(q.qsize()):
            tmp = set()
            for j in range(q.qsize()):
                curword = q.get()
                for i in range(len(curword)):
                    for k in range(26):
                        tmpword = curword[:i]+chr(ord('a')+k)+curword[i+1:]
                        if tmpword == endWord:
                            G[curword].append(tmpword)
                            found = True
                            break
                        if tmpword in word_dict:
                            G[curword].append(tmpword)
                            if tmpword not in tmp:
                                q.put(tmpword)
                                tmp.add(tmpword)
            if found: break
            for word in tmp:
                word_dict.remove(word)
        ans = []
        def traceback(src, dst, path):
            if src == dst:
                ans.append(path[:])
                return
            for word in G[src]:
                path.append(word)
                traceback(word, dst, path)
                path.pop()
        if found:
            path = [beginWord]
            traceback(beginWord, endWord, path)
        return ans
            
                    
                    

思路二:在构建图的时候可以从头结点和尾结点同时构建,每次选择分支数更少的那一端,需要注意的是因为这里构建图的方向会发上反转,因此在找到最短路径时也不能立刻break出来,代码如下:

class Solution:
    def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:
        word_dict = set(wordList)
        if endWord not in word_dict:
            return []
        if beginWord in word_dict:
            word_dict.remove(beginWord)
        from collections import defaultdict
        G = defaultdict(list)
        word_dict.remove(endWord)
        q1 = {beginWord}
        q2 = {endWord}
        found = False
        reverse = False
        while(len(q1)):
            q = set()
            for word in q1:
                for i in range(len(word)):
                    for j in range(26):
                        tmpword = word[:i]+chr(ord('a')+j)+word[i+1:]
                        if tmpword in q2:
                            if reverse:
                                G[tmpword].append(word)
                            else:
                                G[word].append(tmpword)
                            found = True
                        if tmpword in word_dict:
                            if reverse:
                                G[tmpword].append(word)
                            else:
                                G[word].append(tmpword)
                            q.add(tmpword)
            if found: break
            for word in q:
                word_dict.remove(word)
            if len(q) <= len(q2):
                q1 = q
            else:
                q1 = q2
                q2 = q
                reverse = not reverse
        ans = []
        def traceback(src, dst, path):
            if src == dst:
                ans.append(path[:])
                return
            for word in G[src]:
                path.append(word)
                traceback(word, dst, path)
                path.pop()
        if found:
            path = [beginWord]
            traceback(beginWord, endWord, path)
        return ans
            
                    
                    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值