Problem Statement
(Source) Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
- Only one letter can be changed at a time
- Each intermediate word must exist in the word list
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["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.
Tags: Array
, Backtracking
, Breadth-first Search
, String
.
Solution
class Solution(object):
def findLadders(self, beginWord, endWord, wordlist):
"""
:type beginWord: str
:type endWord: str
:type wordlist: Set[str]
:rtype: List[List[int]]
"""
from collections import deque
q = deque([beginWord])
wordlist = set(wordlist)
wordlist.add(endWord)
steps = {word : float('inf') for word in wordlist}
steps[beginWord] = 0
g = {}
min_step = float('inf')
while q:
s = q.popleft()
step = steps.get(s, 0) + 1
if step > min_step:
break
arr = list(s)
for i in xrange(len(arr)):
ord1 = ord(arr[i])
for ord_val in xrange(97, 123):
if ord_val == ord1:
continue
arr[i] = chr(ord_val)
t = ''.join(arr)
if t in steps:
if steps.get(t) > step:
steps[t] = step
q.append(t)
elif steps.get(t) < step:
continue
g.setdefault(t, set()).add(s)
if t == endWord:
min_step = step
arr[i] = chr(ord1)
res = self.bt(endWord, beginWord, g)
for x in res:
x.reverse()
return res
def bt(self, end, start, g):
if start in g.get(end, set()):
return [[end, start]]
else:
res = []
for pre in g.get(end, set()):
for sub in self.bt(pre, start, g):
res.append([end] + sub)
return res