题意:
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
- 说明:
a. 如果不存在这样的转换序列,返回 0。
b. 所有单词具有相同的长度。
c. 所有单词只由小写字母组成。
d. 字典中不存在重复的单词。
e. 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例一:
输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
输出: 5
解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
返回它的长度 5。
示例二:
输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
输出: 0
解释: endWord "cog" 不在字典中,所以无法进行转换。
方法:
广度优先遍历(图的最短路径)
class Solution:
def ladderLength(self, beginWord, endWord, wordList):
"""
:type beginWord: str
:type endWord: str
:type wordList: List[str]
:rtype: int
"""
#如果endWord未在列表中则表示无法完成转换,返回0
if endWord not in wordList:
return 0
#如果beginWord在列表中则将beginWord移除后处理
if beginWord in wordList:
wordList.remove(beginWord)
wordDict = dict()
#遍历wordList后将每一次变化以字典的形式保存{h_t:hit,hot,......}
for word in wordList:
for i in range(len(word)):
tmp = word[:i] + "_" + word[i+1:]
wordDict[tmp] = wordDict.get(tmp, []) + [word]
#栈的定义,集合的创建
stack, visited = [(beginWord, 1)], set()
while stack:
word, step = stack.pop(0)
if word not in visited:
visited.add(word)
#如果到达endWord则返回步数
if word == endWord:
return step
for i in range(len(word)):
tmp = word[:i] + "_" + word[i+1:]
neigh_words = wordDict.get(tmp, []) #如果tmp为wordDict的键,则返回值(单词列表),否则返回空
#入栈出栈操作
for neigh in neigh_words:
if neigh not in visited:
stack.append((neigh, step + 1))
return 0