[LeetCode] 126. Word Ladder II_Hard tag: BFS&DFS
2019-05-26 05:33 Johnson_强生仔仔 阅读(376) 评论(0) 编辑 收藏 举报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 transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:
- Return an empty list 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: [ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
Example 2:
Input: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] Output: [] Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
这个是在[LeetCode] 127. Word Ladder _Medium tag: BFS的基础上,要求求出所有的方案,所以在之前bfs的基础上,加上当时的path,然后将minLength得到之后,将超过minLength的点continue,并且已经visited过的点,再visited的时候current length应该相等。
Update 07/28/2021 多加一个visitedPath, 确保有同样path的newWord不再加入到queue里面,节约时间。
Code:
import collections class Solution(object): def findLadders(self, beginWord, endWord, wordList) : n, wordSet, ans, chars = len(beginWord), set(wordList), [], set(c for word in wordList for c in word ) if endWord not in wordSet: return ans self.bfs(beginWord, endWord, wordSet, chars, ans) return ans def bfs(self, beginWord, endWord, wordSet, chars, ans): queue, visited, minLength = collections.deque([(beginWord, 1, [beginWord])]), {}, -1 while queue: word, length, path = queue.popleft() if word == endWord and (minLength < 0 or length == minLength): ans.append(path) elif (minLength < 0 or length < minLength): for newWord in self.generateNewWord(word, chars): if newWord in wordSet and (newWord not in visited or length + 1 == visited[newWord]): visited[newWord] = length + 1 queue.append((newWord, length + 1, path + [newWord])) def generateNewWord(self, word, chars): n, newWords = len(word), [] for i in range(n): for c in chars: if c != word[i]: newWords.append(word[:i] + c + word[i + 1:]) return newWords
2) 在[LeetCode] 127. Word Ladder _Medium tag: BFS 的基础上将visited变为dictionary
import collections class Solution(object): def findLadders(self, beginWord, endWord, wordList) : wordDic, n, ans, maxDepth = set(wordList), len(beginWord), [], 0 if endWord not in wordDic: return [] chars, queue, visited = set(c for word in wordDic for c in word), collections.deque([(beginWord, [beginWord])]), {beginWord: 0} while queue: word, path = queue.popleft() if word == endWord and (maxDepth == 0 or maxDepth == len(path)): ans.append(path) maxDepth = len(path) elif maxDepth == 0 or len(path) < maxDepth: for i in range(n): for c in chars: newWord = word[:i] + c + word[i + 1:] if (newWord not in visited or visited[newWord] == len(path) + 1) and newWord in wordDic: visited[newWord] = len(path) + 1 queue.append((newWord, path + [newWord])) return ans
Update 07/28/2021 多加一个visitedPath, 确保有同样path的newWord不再加入到queue里面,节约时间。
Code
class Solution: def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]: wordSet, chars = set(wordList), set([c for word in wordList for c in word]) queue, visited,visitedPath = collections.deque([(beginWord, 1, [beginWord])]), {beginWord: 1}, set([tuple([beginWord])]) minLength, ans = None, [] while queue: word, dis, path = queue.popleft() if word == endWord and (minLength is None or dis == minLength): minLength = dis ans.append(path) elif (minLength is None) or (dis < minLength): for i in range(len(word)): for char in chars: if char != word[i]: newWord = word[:i] + char + word[i + 1:] newPath = path + [newWord] if newWord in wordSet and (newWord not in visited or (dis + 1 == visited[newWord] and tuple(newPath) not in visitedPath)): visited[newWord] = dis + 1 visitedPath.add(tuple(newPath)) queue.append((newWord, dis + 1, newPath)) return ans
Added generate newWords function.
class Solution: def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]: chars, wordSet = set([c for word in wordList for c in word]), set(wordList) if endWord not in wordSet: return [] queue, visited, visitedPath = collections.deque([(beginWord, 1, [beginWord])]), {beginWord: 1}, set([tuple([beginWord])]) maxLen = None ans = [] while queue: word, dis, path = queue.popleft() if word == endWord and (maxLen is None or dis == maxLen): ans.append(path) maxLen = dis elif maxLen is None or dis < maxLen: newWords = self.generateNewWords(word, chars) for newWord in newWords: newPath = path + [newWord] if newWord in wordSet and (newWord not in visited or (visited[newWord] == dis + 1 and tuple(newPath) not in visitedPath)): visited[newWord] = dis + 1 visitedPath.add(tuple(newPath)) queue.append((newWord, dis + 1, newPath)) return ans def generateNewWords(self, word, chars): newWords = [] for i in range(len(word)): for c in chars: if c != word[i]: newWords.append(word[:i] + c + word[i + 1:]) return newWords