我正在尝试解决这个问题:
给出两个单词(beginWord和endWord),以及字典的单词列表, 查找从beginWord到的最短转换序列的长度 endWord,例如:
一次只能更改一个字母。每个变换的词必须 存在于单词列表中。注意beginWord不是转换后的单词。 注意:
如果没有这样的转换序列,则返回0。所有的单词都有 相同的长度。所有单词仅包含小写字母 字符。您可以假设单词列表中没有重复项。你可以 假设beginWord和endWord为非空并且不相同。
https://leetcode.com/problems/word-ladder/ 我正确的工作代码:
from collections import Counter, defaultdict, deque
def can_change(x, y):
diff = 0
for u, v in zip(x, y):
if u != v:
diff += 1
if diff>1:
return False
return diff == 1
class Solution:
def ladderLength(self, start, end, dict):
graph = defaultdict(list)
words = set(dict+[start])
for w1 in words:
for w2 in words:
if w1 != w2:
if can_change(w1, w2):
graph[w1].append(w2)
def bfs(node):
queue = deque([(node, 1)])
seen = {node}
while queue:
node, count = queue.pop()
if node == end:
return count
for neb in graph[node]:
if neb not in seen:
seen.add(neb)
queue.appendleft((neb, count+1))
return 0
return bfs(start)
在大型测试用例上超时。如何在时间复杂度方面进行优化?
答案 0 :(得分:0)
我会尽量避免使用邻接表显式定义图-我认为这是多余的。
相反,您可以尝试隐式运行BFS。 伪代码:
Q = empty queue
beginWord.depth = 0
Q.enqueue(beginWord)
while Q is not empty:
w = Q.dequeue
for l in dictionary:
if l is a one char transform on w:
if l == endWord:
return w.depth+1
else:
l.depth = w + 1
Q.enqueue(l)
remove l from the dictionary.
return 0
我认为,此方法与您使用的BFS方法非常相似。它以BFS方式扫描“图形”,跟踪从beginWord可以找到的单词以及当前的搜索深度。如果找到endWord,则返回其深度。
这里的主要区别是我们不创建用于对整个字典建模的图形。我们确实扫描了广度优先样式的搜索,但我们避免跟踪以后不使用的信息-例如路径的边缘,不可达的单词等。
此处的渐近运行时间为O(nX),X是从beginWord可到达的单词数。在最坏的情况下,它不能胜过您的算法,但在其他许多情况下,它也可以。
它还为您节省了在构建图形之后必须执行的BFS搜索,并且将证明可以访问的单词从列表中删除,从而减少了常量。