题目:
字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:
wordList是一个英文单词,意思是“单词列表”。如果您需要查找字典,可以使用在线词典,例如柯林斯词典、有道词典等。这些在线词典可以帮助您查找单词的定义、拼写、发音等信息。
- 序列中第一个单词是 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 <= 10
- endWord.length == beginWord.length
- 1 <= wordList.length <= 5000
- wordList[i].length == beginWord.length
- beginWord、endWord 和 wordList[i] 由小写英文字母组成
- beginWord != endWord
- wordList 中的所有字符串 互不相同
完整代码及注释(基于选项D):
class Solution(object):
def __init__(self):
self.count = 0
def ladderLength(self, beginWord, endWord, wordList):
"""
:type beginWord: str
:type endWord: str
:type wordList: List[str]
:rtype: int
"""
# • 序列中最后一个单词是 endWord,如果endWord not in wordList则返回0
#
if endWord not in wordList:
return 0
# • 若序列中第一个单词就是 beginWord,则从wordlist中移除,beginWord 不需要在 wordList 中。
# wordList = ["hot", "dot", "dog", "lot", "log", "cog"]
if beginWord in wordList:
wordList.remove(beginWord)
wordDict = dict()
#wordList中每个单词遍历,按同一位置具有相同字母的map如下:
#本例子哈希:{'_ot': ['hot', 'dot', 'lot'], 'h_t': ['hot'], 'ho_': ['hot'], 'd_t': ['dot'], 'do_': ['dot', 'dog'],
# '_og': ['dog', 'log', 'cog'], 'd_g': ['dog'], 'l_t': ['lot'], 'lo_': ['lot', 'log'], 'l_g': ['log'], 'c_g': ['cog'], 'co_': ['cog']}
for word in wordList:
#当前单词每个字母遍历
for i in range(len(word)):
#按顺序将当前词中每个字母轮流替换成“_”并临时存储在tmp中
tmp = word[:i] + "_" + word[i + 1 :]
#将tmp作为key,存储在字典中,对应的值为同一位置存在该key的所有单词,即某一位置具有相同字母的单词归类
wordDict[tmp] = wordDict.get(tmp, []) + [word]
#然后在基于wordList的map中查找是否有temp,如果存在temp,则把temp添加到queue当中,还是别忘了要将当前的“hit”从队列中remove掉,
# 并把相应的visited设置已以访问过,采用set方法,访问过就有记录,自动去重,不记录已访问次数。
stack, visited = [(beginWord, 1)], set()
while stack:
#如果stack不为空,则 stack分解为word和step
word, step = stack.pop(0)
#如果word未被访问过,则记录
if word not in visited:
visited.add(word)
#如果是结尾单词,则返回锁经历的搜索次数
if word == endWord:
return step
for i in range(len(word)):
tmp = word[:i] + "_" + word[i + 1 :]
#python dict.get“Python中的字典(Dictionary)是以键值对的形式存储数据的,get()方法可以返回指定键的值,如果该键不存在的话,返回默认值。
# 语法 dict.get(key, default=None) 参数 key:需要查找的键。 default:如果查找的键不存在的话,返回default的值。默认为None。
#该方法取得具有同样词根的一组词,如果没有,则返回空,
neigh_words = wordDict.get(tmp, [])
for neigh in neigh_words:
if neigh not in visited:
#如果没有访问过(即出现新的路径),则是一条有效搜索路径,可将该word添加入stack,并且更新step
#同级的不同单词,step记录一致
stack.append((neigh, step + 1))
return 0
if __name__ == '__main__':
s = Solution()
beginWord = "hit"
endWord = "cog"
wordList = ["hot", "dot", "dog", "lot", "log", "cog"]
result=s.ladderLength(beginWord, endWord, wordList)
print(result)
说明:
# • 序列中最后一个单词是 endWord,如果endWord not in wordList则返回0
#
if endWord not in wordList:
return 0
# • 若序列中第一个单词就是 beginWord,则从wordlist中移除,beginWord 不需要在 wordList 中。
# wordList = ["hot", "dot", "dog", "lot", "log", "cog"]
if beginWord in wordList:
wordList.remove(beginWord)
wordDict = dict()
#wordList中每个单词遍历,按同一位置具有相同字母的map如下:
#本例子哈希:{'_ot': ['hot', 'dot', 'lot'], 'h_t': ['hot'], 'ho_': ['hot'], 'd_t': ['dot'], 'do_': ['dot', 'dog'],
# '_og': ['dog', 'log', 'cog'], 'd_g': ['dog'], 'l_t': ['lot'], 'lo_': ['lot', 'log'], 'l_g': ['log'], 'c_g': ['cog'], 'co_': ['cog']}
for word in wordList:
#当前单词每个字母遍历
for i in range(len(word)):
#按顺序将当前词中每个字母轮流替换成“_”并临时存储在tmp中
tmp = word[:i] + "_" + word[i + 1 :]
#将tmp作为key,存储在字典中,对应的值为同一位置存在该key的所有单词,即某一位置具有相同字母的单词归类
wordDict[tmp] = wordDict.get(tmp, []) + [word]
#然后在基于wordList的map中查找是否有temp,如果存在temp,则把temp添加到queue当中,还是别忘了要将当前的“hit”从队列中remove掉,
# 并把相应的visited设置已以访问过,采用set方法,访问过就有记录,自动去重,不记录已访问次数。
stack, visited = [(beginWord, 1)], set()
while stack:
#如果stack不为空,则 stack分解为word和step
word, step = stack.pop(0)
#如果word未被访问过,则记录
if word not in visited:
visited.add(word)
#如果是结尾单词,则返回锁经历的搜索次数
if word == endWord:
return step
for i in range(len(word)):
tmp = word[:i] + "_" + word[i + 1 :]
#python dict.get“Python中的字典(Dictionary)是以键值对的形式存储数据的,get()方法可以返回指定键的值,如果该键不存在的话,返回默认值。
# 语法 dict.get(key, default=None) 参数 key:需要查找的键。 default:如果查找的键不存在的话,返回default的值。默认为None。
#该方法取得具有同样词根的一组词,如果没有,则返回空,
neigh_words = wordDict.get(tmp, [])
for neigh in neigh_words:
if neigh not in visited:
#如果没有访问过(即出现新的路径),则是一条有效搜索路径,可将该word添加入stack,并且更新step
#同级的不同单词,step记录一致
其他三个选项的错误均出现在while stack循环体中,具体为:
A、选项代码局部:
while stack:
word, step = stack.pop(0)
if word not in visited:
visited.add(word)
if word == endWord:
return step
for i in range(len(word)):
#字符的连接符号应为+,*是针对数值计算的
tmp = word[:i] * "_" * word[i * 1 :]
neigh_words = wordDict.get(tmp, [])
for neigh in neigh_words:
if neigh not in visited:
stack.append((neigh, step + 1))
return 0
B、选项代码局部:
while stack:
word, step = stack.pop(0)
if word not in visited:
visited.add(word)
#错误点: word < endWord错误,应该是处理到最后一个单词(word == endWord)再return
if word < endWord:
return step
for i in range(len(word)):
tmp = word[:i] + "_" + word[i + 1 :]
neigh_words = wordDict.get(tmp, [])
for neigh in neigh_words:
if neigh not in visited:
stack.append((neigh, step + 1))
return 0
C、选项代码局部:
while stack:
word, step = stack.pop(0)
if word not in visited:
visited.add(word)
if word == endWord:
return step
for i in range(len(word)):
tmp = word[:i] + "_" + word[i + 1 :]
neigh_words = wordDict.get(tmp, [])
for neigh in neigh_words:
#语法错误:and in不能连用
if neigh and in visited:
stack.append((neigh, step + 1))
return 0