Given two words (beginWordand endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time.
Each transformed word must exist in the word list. Note that beginWordis not a transformed word.
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5.
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 _endWordare non-empty and are not the same.
The Idea: Build a graph. For this graph define a link between two words a and b if difference(a,b) == 1. Do this for every word. Then BFS through this graph, while using a visited map prohibits cyclic roots.
Complexity:O(n^2 * m + n) time where m is length of the word, and n is the number of words. O(n^2 * m) for prepossessing, and then O(n) time for BFS. Space complexity will be O(n^2 + n + n); respectively for the graph itself, the visited set, and queue.
import queueclassSolution:defdifference(self,a,b):""" :param a: str - word1 :param b: str - word2 :return: int - number of different characters between a and b under the assumption that len(a) = len(b) """ diff =0for c1, c2 inzip(a,b):if c1 != c2: diff +=1return diffdefget_graph_diff_1(self,word_list):""" :param word_list: List[str] - list of words :return: 2d map - relationship of words that differ by one connection """ return dict([word, set(word2 for word2 in word_list if self.difference(word, word2) == 1)] for word in word_list)
defladderLength(self,beginWord,endWord,wordList):""" :param beginWord: str - word to start with :param endWord: str - target word to end :param wordList: List[str] - bank of valid words (same length) :return: int - minimum distance to get between start and end words """ wordList.append(beginWord) graph = self.get_graph_diff_1(wordList) visited =set(word for word in wordList) q = queue.Queue() q.put((beginWord, 1))whilenot q.empty(): front = q.get()if visited.__contains__(front[0]): visited.remove(front[0])for word in graph[front[0]]:if word == endWord:return front[1]+1if visited.__contains__(word): q.put((word, front[1] +1))return0obj =Solution()word_list = ["hot","dot","dog","lot","log"]print(obj.ladderLength("hit", "cog", word_list))