127. 单词接龙
字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:
序列中第一个单词是 beginWord 。序列中最后一个单词是 endWord 。每次转换只能改变一个字母。转换过程中的中间单词必须是字典 wordList 中的单词。给你两个单词 beginWord 和 endWord 和一个字典 wordList ,找到从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0。
示例 1:
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]输出:5解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
示例 2:
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]输出:0解释:endWord "cog" 不在字典中,所以无法进行转换。
提示:
1 <= beginWord.length <= 10endWord.length == beginWord.length1 <= wordList.length <= 5000wordList[i].length == beginWord.lengthbeginWord、endWord 和 wordList[i] 由小写英文字母组成beginWord != endWordwordList 中的所有字符串 互不相同
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-ladder
Link:https://leetcode.com/problems/word-ladder/
宽度优先搜索
O(NL)
'hit'|'hot'/ \'dot' 'lot'| |'dog' 'log'\ /'cog'
从开始单词到结束单词之间会形成一张图,也就是说,用宽度优先搜索,找到路径最短的变换
问题在于如何找到,只差一个字母的所有邻居,一点点变化,时间复杂度是不一样的
时间复杂度: O(N * N * L)
from collections import dequeclass Solution:def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:wordset = set(wordList)if endWord not in wordset:return 0distance = 0visited = set([beginWord])queue = deque([beginWord])while len(queue) > 0:count = len(queue)distance += 1for i in range(count):word = queue.popleft()if word == endWord:return distancefor target in wordset:if target not in visited and self.changeable(word, target):queue.append(target)visited.add(target)return 0def changeable(self, beginWord: str, endWord: str) -> bool:diff = 0for i in range(len(beginWord)):diff += 0 if beginWord[i] == endWord[i] else 1return diff == 1
优化的时间复杂度: O(N * 26 * L)
from collections import dequeclass Solution:def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:wordset = set(wordList)if endWord not in wordset:return 0distance = 0visited = set([beginWord])queue = deque([beginWord])while len(queue) > 0:count = len(queue)distance += 1for i in range(count):word = queue.popleft()if word == endWord:return distancefor target in self.findNeighbors(word, wordset, visited):queue.append(target)visited.add(target)return 0def findNeighbors(self, word: str, wordset: set, visited: set) -> [str]:res = []for i in range(len(word)):for char in 'abcdefghijklmnopqrstuvwxyz':candidate = word[:i] + char + word[i + 1:]if candidate == word:continueif candidate in visited:continueif candidate not in wordset:continueres.append(candidate)return res
精简代码如下:
from collections import dequeclass Solution:def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:wordset = set(wordList)queue = deque([beginWord])distance = 0while len(queue) > 0:count = len(queue)distance += 1for i in range(count):word = queue.popleft()if word == endWord:return distancefor j in range(len(word)):for k in 'abcdefghijklmnopqrstuvwxyz':candidate = word[:j] + k + word[j + 1:]if candidate in wordset:queue.append(candidate)wordset.remove(candidate)return 0
--End--