代码改变世界

[LeetCode] 127. Word Ladder _Medium tag: BFS

2018-07-04 10:16  Johnson_强生仔仔  阅读(250)  评论(0编辑  收藏  举报

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

Example 1:

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

Output: 5

Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Example 2:

Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

Output: 0

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

这个题的思路很明显也是BFS, 因为我们是一层一层的scan, 所以一旦找到endword, 那么肯定目前的distance是最小的. 我们怎么样BFS呢, 把目前的word的每一位分别用26位小写字母去代替,
得到一个new_word, 看new_word是否在wordlist里面 并且没有visited过, 如果是,append 进入queue, 并且将其标志为visited. 这里有个improve的是不用代替26个字母, 而用
chars = set(c for word in wordlist for c in word), 就是将wordlist里面所有的字母放到一个list里面, 只用试这些字母就行了, 加快一点进程. edge case的话就是如果endword
不在wordlist里面.

1. Constraints
1) beginWord and endWord is not the same
  2) all words are lower cases # 如果我们chars用improve的方法,也就是思路里面的方式, 就算有大写字母也无所谓.
  3) no duplicates in wordlist
  4) wordlist can be empty
  5) one letter change in one time
  6) all words has the same length
  7) beginWord and endWord not empty
  8) edge case, endword has to be in wordlist, otherwise return 0

2. Ideas

BFS: T: O(m*n) S: O(m*n) m: length of wordlist, n length of each word

1) edge case, endword not in set(wordlist) => 0
2) queue(init: (beginword, 1)), visited (init: set())
3) while queue: word, dis = queue.popleft(), if word == endword, return dis
4) else:将word的每一位分别用chars里面的字母代替, 然后看是否在wordlist里面并且没有被visited过, 如果是, append进入queue, 并且tag为visited
5) end loop, return 0


3. code
 1 class Solution:
 2     def wordLadder(self, beginWord, WordList, endWord):
 3         len_word, w_list = len(beginWord), set(WordList) # set(WordList) 非常重要,否者的话time limit
 4         if endWord not in w_list: return 0  # edge case
 5         queue, visited = collections.deque([(beginWord, 1)]), set()
 6         chars = set(c for word in w_list for c in word)
 7         while queue:
 8             word, dis = queue.popleft()
 9             if word == endWord: return dis
10             else:
11                 for i in range(len_word):
12                     for c in chars:
13                         new_word = word[:i] + c + word[i+1:]
14                         if new_word in w_list and new_word not in visited:
15                             queue.append((new_word, dis+1))
16                             visited.add(new_word)
17         return 0

 

4. test cases:

   1) wordList is empty or all wordlist not include endWord.  => 0

    2) 

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

Output: 5