標籤:
Word Ladder II
描述
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start
to end, such that:
• Only one letter can be changed at a time
• Each intermediate word must exist in the dictionary
For example, Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Note:
• All words have the same length.
• All words contain only lowercase alphabetic characters.
題意:給定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(是字典類型)來記錄單詞的前驅。比如prevMap={cog:[log, dog]}表示cog的前驅是:log和dog。
3,在word ladder這道題中我們使用了隊列,在word ladder ii中也需要使用隊列,只不過在這個程式中使用了兩個set()來類比隊列(candidates)。candidates[previous]中儲存的是前一層的單詞。如{dot,lot}為第3層單詞。在程式開始執行時,先將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’], ‘lot’:[‘hot’],’dot’:[‘hot’], ‘hot’:[‘hit’]},這個prevMap可以使用DFS來重建每一條路徑。
本解法來自:
http://www.cnblogs.com/zuoyuan/p/3697045.html
但是很多細節不明白,尋求大家的協助.
1 class Solution: 2 # @param start, a string 3 # @param end, a string 4 # @param dict, a set of string 5 # @return a list of lists of string 6 def findLadders(self, start, end, dict): 7 def buildpath(path, word): # path is a list; word is a string 8 if len(prevMap[word])==0: #prevMap: dict #Blank prevMap means all the node in the path is visited 9 path.append(word); 10 currPath=path[:] # hard copy path to currPath. No link between pat and currPath11 currPath.reverse(); 12 result.append(currPath)13 path.pop(); #remove the end element14 return15 path.append(word)16 for iter in prevMap[word]: # reverse the path,17 buildpath(path, iter)18 path.pop()19 20 result=[]21 prevMap={} # prevMap is a dict22 length=len(start)23 for i in dict: #dict: is a set24 prevMap[i]=[] # set the value for each key as blank string25 candidates=[set(),set()]; current=0; previous=126 candidates[current].add(start) # set0 add start27 while True:28 current, previous=previous, current #下一次迴圈開始時,上一次迴圈的candidates[current]變成了candidates[previous],而上一次迴圈的candidates[previous]變成了candidates[current]並清空29 for i in candidates[previous]: dict.remove(i) #先將candidates[previous]中的單詞(前一層的單詞)在dict中刪除30 candidates[current].clear() #再將candidates[current]清空31 for word in candidates[previous]: #再據candidates[previous]中的單詞尋找下一層的單詞32 for i in range(length):33 part1=word[:i]; part2=word[i+1:]34 for j in ‘abcdefghijklmnopqrstuvwxyz‘:35 if word[i]!=j:36 nextword=part1+j+part237 if nextword in dict:38 candidates[current].add(nextword) #將下一層存入candidates[current]中39 prevMap[nextword].append(word) #同時將單詞存入前驅單詞表中40 if len(candidates[current])==0: return result #當集合為空白,返回結果41 if end in candidates[current]: break #當迴圈中的candidates[current]中出現了end單詞時,說明我們的路徑已經找出來了,工作完成了。42 buildpath([], end) #重建每一條路徑。prevMap is a dict,這個prevMap可以使用DFS來重建每一條路徑。43 return result
[python leetcode] Word Ladder II (very hard)[非常難,放棄]