[leetcode]Word Ladder II @ Python


[leetcode]Word Ladder II @ Python

原題地址:http://oj.leetcode.com/problems/word-ladder-ii/

參考文獻:http://blog.csdn.net/doc_sgl/article/details/13341405

       http://chaoren.is-programmer.com/

題意:給定start單詞,end單詞,以及一個dict字典。要求找出start到end的所有最短路徑,路徑上的每個單詞都要出現在dict中,且每次改變一個字母。如start="hit"; end="cog"; dict={"hot","dot","dog","lot","log"},則答案為:[["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]。這是leetcode oj給的例子。我在實現的時候發現這個例子有點問題:end單詞不在dict中。實際的測試用例應該是start和end單詞都在dict中的,因為如果提前做一個刪除start或者end單詞的操作的話,就通不過了。我用正確的程序去測試oj給的這個例子也無法通過,就姑且認為start單詞和end單詞都在dict中吧,這樣寫出來的程序才能通過。

Word Ladder II這一道題還是比較難的,是leetcode oj中通過率最低的一道題。而由於我一直在用python來刷題,且一直在網上找不到用python寫的解法,自己又寫不出來,所以參考了網上的C++解法以及kitt的python程序,在此表示感謝。

 解題關鍵點:1,這里的dict是python中的set()類型。

       2,使用前驅單詞表prevMap,是python中的字典類型。用來記錄單詞的前驅。比如prevMap={cog:[log, dog]}表示cog的前驅是:log和dog。

       3,在word ladder這道題中我們使用了隊列,在word ladder ii中也需要使用隊列,只不過在這個程序中使用了兩個set()來模擬隊列。candidates[previous]中存儲的是前面一層的單詞。如{dot,lot}為第三層單詞。在程序開始執行時,現將前面一層的單詞即candidates[previous]中的單詞在dict中刪除,再將candidates[current]清空,然后根據candidates[previous]中的單詞尋找下一層的單詞,如{dot,lot}的下一層為{dog,log},並將{dog,log}存入candidates[current]中,同時將單詞存入前驅單詞表中。下一次循環開始時,上一次循環的candidates[current]變成了candidates[previous],而上一次循環的candidates[previous]變成了candidates[current]並清空。如此反復執行,當某一次循環中的candidates[current]中出現了end單詞時,說明我們的路徑已經找出來了,工作完成了。

       4,程序中使用了一個子函數buildpath來重建每一條路徑。如oj給的例子所產生的prevMap={cog:[log,dog], log:[lot], dog:[dot], dot:[hot], lot:[hot], hot:[hit]},這個prevMap可以使用DFS來重建每一條路徑。

源代碼:

class Solution:
    # @param start, a string
    # @param end, a string
    # @param dict, a set of string
    # @return a list of lists of string
    def findLadders(self, start, end, dict):
        def buildpath(path, word):
            if len(prevMap[word])==0:
                path.append(word); currPath=path[:]
                currPath.reverse(); result.append(currPath)
                path.pop();
                return
            path.append(word)
            for iter in prevMap[word]:
                buildpath(path, iter)
            path.pop()
        
        result=[]
        prevMap={}
        length=len(start)
        for i in dict:
            prevMap[i]=[]
        candidates=[set(),set()]; current=0; previous=1
        candidates[current].add(start)
        while True:
            current, previous=previous, current
            for i in candidates[previous]: dict.remove(i)
            candidates[current].clear()
            for word in candidates[previous]:
                for i in range(length):
                    part1=word[:i]; part2=word[i+1:]
                    for j in 'abcdefghijklmnopqrstuvwxyz':
                        if word[i]!=j:
                            nextword=part1+j+part2
                            if nextword in dict:
                                prevMap[nextword].append(word)
                                candidates[current].add(nextword)
            if len(candidates[current])==0: return result
            if end in candidates[current]: break
        buildpath([], end)
        return result

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM