Word Ladder II 解题总结

前后一共提交了10次才AC,主要的问题在于超时。总结一下解题思路的演变

大体的思路就是根据单词间的距离(距离为1两单词相邻)生成图,在图上搜索从beginWord到endWord的全部最短路径。

全图+广搜深度+深搜路径

全图:两两比较wordlist中的距离,距离为1两节点相邻,最终生成以wordlist为顶集的邻接链表

广搜深度:把经典的广搜算法稍微修改一下变成按层入队出队,求得beginWord到endWord的距离

深搜路径:到达上面求的深度如果还没有搜到endWord就返回空值

第一次尝试没有考虑时间问题,所以不出所料的超时了,不过先跑起来再说嘛

全图+有向无环生成子图+深搜路径

全图跟之前一样,没有变化

有向无环图:在全图上的生成子图,是按照与benginWord距离分层的有向无环图,依旧由广搜得到这个有向无环生成子图,一旦某层中出现了endWord就结束搜索

深搜路径:得益于得到子图的特殊结构,一旦搜到endWord,那么当前的路径就一定是最短的

提交之后依旧超时,用kernprof看了一下时间分布,大部分的时间都在用在生成全图上,单词两两比较的方法效率也是捉急

有向无环子图 + 深搜路径

之前的主要问题在于花费大量时间去生成全图,这个图中大部分信息对需要解决的问题是没有用的。现在从问题入手,直接从beginWord开始广度搜索,在搜索的过程中建立有向无环子图的临界链表,这样就省去了大量冗余信息的计算。

另一个问题就是寻找相邻单词的策略,这里换成枚举当前单词相邻单词,再去wordlist中检查是否存在,这样时间效率就从之前的wordlist大小主导变成了单词长度主导,当wordlist的规模很大时,效率的提升会很明显

提交之后依旧超时,程序里肯定还是做了哪些无用功

有向无环子图+逆邻接链表+深搜路径

之前的无用功就是在深搜路径的过程中,很多路径的最后一个单词不是要求的endWord。但是我们肯定的是如果从endWord开始搜beginWord,那么所有的路径最后一个单词一定是beginWord,因为在生成这个有向无环子图的时候只有一个起点。从endWord开始搜索就需要建立原先有向无环子图的逆邻接链表。

这个思路提交之后终于AC了,670ms

最终代码

import string

class Solution(object):
    # @profile
    def findLadders(self, beginWord, endWord, wordlist):
        # @profile
        def creatDict():
            adj_dict = {}
            level = set([beginWord])
            wordlist.remove(beginWord)

            while len(level) > 0:
                if endWord in level:
                    break
                next_level = set()
                for w1 in level:
                    for i in range(len(w1)):
                        for c in string.lowercase:
                            w2 = w1[:i] + c + w1[i+1:]
                            if w2 in next_level:
                                adj_dict[w2].append(w1)
                            if w2 in wordlist:
                                wordlist.remove(w2)
                                adj_dict[w2] = [w1]
                                next_level.add(w2)
                level = next_level
            return adj_dict

        # @profile
        def DFS(ew):
            if ew == beginWord:
                return [[ew]]
            else:
                path = []
                if not adj_dict.has_key(ew):
                    return path
                for tw in adj_dict[ew]:
                    path += [p + [ew] for p in DFS(tw)]
                return path

        adj_dict = creatDict()
        return DFS(endWord)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值