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:
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.
defbfs(self, beginWord, endWord, dict, visited): queue = deque([beginWord]) visited.add(beginWord) while queue: word = queue.popleft() if word == endWord: return dict[word]
neighbors = self.get_next_words(word, dict) for neighbor in neighbors: if neighbor notin visited: queue.append(neighbor) visited.add(neighbor) dict[neighbor] = dict[word] + 1
return0
defget_next_words(self, word, dict): res = [] for i in range(len(word)): for c in string.ascii_lowercase: # or use 'abcdefghijklmnopqrstuvwxyz' if c == word[i]: continue new_word = word[:i] + c + word[i + 1:] if new_word in dict: res.append(new_word) return res
publicintladderLength(String beginWord, String endWord, List<String> wordList){ // This is a dict and also keeps track of distance Map<String, Integer> dict = getDict(wordList); // Make sure endWord is in the dict and can be the next word //dict.put(endWord, 0); dict.put(beginWord, 1); Set<String> visited = new HashSet<>(); Queue<String> q = new LinkedList<>(); q.offer(beginWord); visited.add(beginWord); while(!q.isEmpty()) { String word = q.poll(); if(endWord.equals(word)) return dict.get(word); List<String> nextWords = getNextWords(word, dict); for(String s : nextWords) { if(visited.contains(s)) continue; q.offer(s); visited.add(s); dict.put(s, dict.get(word) + 1); } } return0; }
forward_queue, backward_queue = deque([beginWord]), deque([endWord]) forward_visited, backward_visited = set([beginWord]), set([endWord]) while forward_queue and backward_queue: total_dis = self.bfs_from_start_or_end(graph, forward_queue, forward_distance, backward_distance) if total_dis > 0: return total_dis total_dis = self.bfs_from_start_or_end(graph, backward_queue, backward_distance, forward_distance) if total_dis > 0: return total_dis return0
defbfs_from_start_or_end(self, graph, queue, distance, target_dict): word = queue.popleft() if word in target_dict and target_dict[word] > 0: # the forward distance has all words initially return distance[word] + target_dict[word]
neighbors = graph[word] for neighbor in neighbors: #if neighbor in visited: if neighbor in distance: continue queue.append(neighbor) # visited.add(neighbor) distance[neighbor] = distance[word] + 1 return0