原題
給出兩個單詞(start和end)和一個字典,找出所有從start到end的最短轉換序列
比如:
1.每次只能改變一個字母。
2.變換過程中的中間單詞必須在字典中出現。
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
返回
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
注意
- 所有單詞具有相同的長度。
- 所有單詞都只包含小寫字母。
解題思路
- 首先,善用一個條件,所有的單詞長度相同
- 建立一個index,作用就是把去掉某一個位置的字母后,剩余部分相同的放入一個桶中。為了優化時間復雜度。比如
"abcd" -> (1, bcd) <- "fbcd"
- BFS一遍,確定為一個單詞在圖中的第幾層
- DFS一遍,找到每一個可行的路線。此時BFS的作用就是從第n層只能往n+1層走,以保證最短路徑
- 為什么使用
dict.get(key)
而不是dict[key]
?
# 可以設定一個default value, 如果key不存在,就建立相應的key-value pair
a = dictionary.get("bogus", None) # return None
a = dictionary["bogus"] # raise KeyError
完整代碼
import Queue
class Solution(object):
def buildIndex(self, length, dict):
indexes = []
for i in range(length):
index = {}
for word in dict:
entry = word[:i] + word[i + 1:]
words = index.get(entry, [])
words.append(word)
index[entry] = words
indexes.append(index)
return indexes
def getNextWord(self, word):
res = []
for i in range(len(word)):
entry = word[:i] + word[i + 1:]
if entry in self.indexes[i]:
for nextWord in self.indexes[i][entry]:
if nextWord != word:
res.append(nextWord)
return res
def BFS(self, start, end):
self.distance = {}
self.distance[start] = 0
q = Queue.Queue()
q.put(start)
while not q.empty():
head = q.get()
for nextWord in self.getNextWord(head):
if nextWord not in self.distance:
self.distance[nextWord] = self.distance[head] + 1
q.put(nextWord)
def DFS(self, current, target, path):
if current == target:
self.result.append(path[:])
return
for word in self.getNextWord(current):
if self.distance[word] - 1 == self.distance[current]:
self.DFS(word, target, path + [word])
def findLadders(self, beginWord, endWord, wordlist):
"""
:type beginWord: str
:type endWord: str
:type wordlist: Set[str]
:rtype: List[List[int]]
"""
if beginWord is None or endWord is None or len(beginWord) != len(endWord):
return []
if beginWord not in wordlist or endWord not in wordlist:
return []
self.indexes = self.buildIndex(len(beginWord), wordlist)
self.BFS(beginWord, endWord)
self.result = []
if beginWord in self.distance:
self.DFS(beginWord, endWord, [beginWord])
return self.result