Word Ladder 运行时复杂度
Word Ladder runtime complexity
我正在尝试解决以下问题:
给定一个 beginWord,say pig,一个 endWord,say phi,以及一个单词列表 wordList,say [phg, phi]。 beginword每次允许改变一个字符,并且改变后的词需要在wordList中。我需要一种算法来找到实现转换的最少步骤。在我的示例中,我们可以执行 pig -> phg -> phi。而且所有涉及的单词都是相同的长度。
我的解决方案是使用 BFS:
queue;
level = 0;
queue.add(beginWord);
while(queue is not empty){
for(i looping from 0 to the size of the queue){
curr = the first element in the queue;
if curr is endWord, then returns level + 1;
for(j starting from 0 to the length of curr){
for(c starting from a to z){
replaced = replace the jth character of curr with c;
if we have never seen replaced before and it is contained in wordList, then add it to the queue.
}
}
}
}
return 0;
现在我正在努力想出这个算法的运行时复杂度。假设words的长度是$M$,wordList的长度是N
。我的想法如下:
对于每个中间词,您有 26**M
个选择,在最坏的情况下,可能需要访问 wordList 中的所有 N
个词,因此总共有 N * 26 ** M
个。但是,由于我们要求所有转换都在 wordList 中,因此实际上,在每个中间词处,您最多有 N-1
个选择。因此,在我看来,运行时复杂度应该是 O(N(N - 1))
.
对吗?我不这么认为,因为即使在每个中间词中,只有 N-1
种可能的转换,人们确实会花费操作来检查其中哪些 N-1
个是有效的,方法是遍历整个单词和用 26
种可能性替换了它的每个字符。
我知道问题已经被问过了here。但是那里没有答案,我不同意他们的分析。
所以就算法复杂度而言:
queue;
level = 0;
queue.add(beginWord);
while(queue is not empty){
for(i looping from 0 to the size of the queue){
curr = the first element in the queue;
if curr is endWord, then returns level + 1;
for(j starting from 0 to the length of curr){
for(c starting from a to z){
replaced = replace the jth character of curr with c;
if we have never seen replaced before and it is contained in wordList, then add it to the queue.
}
}
}
}
return 0;
假设最内层的循环使用 trie 或哈希表进行查找(不会比这更有效),内部条件需要 O(n)
:
while(queue is not empty){
for(i looping from 0 to the size of the queue){
curr = the first element in the queue;
if curr is endWord, then returns level + 1;
for(j starting from 0 to the length of curr){
for(c starting from a to z){
O(n)
}
}
}
}
下一个最里面的循环迭代了26次,所以还是O(n)
:
while(queue is not empty){
for(i looping from 0 to the size of the queue){
curr = the first element in the queue;
if curr is endWord, then returns level + 1;
for(j starting from 0 to the length of curr){
O(n)
}
}
}
下一个循环遍历字符串的长度,所以又是 n
步。额外的步骤要么是恒定时间的,要么是线性的(O(n)
),所以我们可以忽略它们:
while(queue is not empty){
for(i looping from 0 to the size of the queue){
O(n ^ 2)
}
}
这个 for 循环现在完全没用了。我们可以简单地删除它,而不是直接在 while
循环中轮询队列。 while
循环采用 O(m)
步,其中 m
是单词列表中的单词数。所以总的时间复杂度是 O(n^2 * m)
.
我正在尝试解决以下问题:
给定一个 beginWord,say pig,一个 endWord,say phi,以及一个单词列表 wordList,say [phg, phi]。 beginword每次允许改变一个字符,并且改变后的词需要在wordList中。我需要一种算法来找到实现转换的最少步骤。在我的示例中,我们可以执行 pig -> phg -> phi。而且所有涉及的单词都是相同的长度。
我的解决方案是使用 BFS:
queue;
level = 0;
queue.add(beginWord);
while(queue is not empty){
for(i looping from 0 to the size of the queue){
curr = the first element in the queue;
if curr is endWord, then returns level + 1;
for(j starting from 0 to the length of curr){
for(c starting from a to z){
replaced = replace the jth character of curr with c;
if we have never seen replaced before and it is contained in wordList, then add it to the queue.
}
}
}
}
return 0;
现在我正在努力想出这个算法的运行时复杂度。假设words的长度是$M$,wordList的长度是N
。我的想法如下:
对于每个中间词,您有 26**M
个选择,在最坏的情况下,可能需要访问 wordList 中的所有 N
个词,因此总共有 N * 26 ** M
个。但是,由于我们要求所有转换都在 wordList 中,因此实际上,在每个中间词处,您最多有 N-1
个选择。因此,在我看来,运行时复杂度应该是 O(N(N - 1))
.
对吗?我不这么认为,因为即使在每个中间词中,只有 N-1
种可能的转换,人们确实会花费操作来检查其中哪些 N-1
个是有效的,方法是遍历整个单词和用 26
种可能性替换了它的每个字符。
我知道问题已经被问过了here。但是那里没有答案,我不同意他们的分析。
所以就算法复杂度而言:
queue;
level = 0;
queue.add(beginWord);
while(queue is not empty){
for(i looping from 0 to the size of the queue){
curr = the first element in the queue;
if curr is endWord, then returns level + 1;
for(j starting from 0 to the length of curr){
for(c starting from a to z){
replaced = replace the jth character of curr with c;
if we have never seen replaced before and it is contained in wordList, then add it to the queue.
}
}
}
}
return 0;
假设最内层的循环使用 trie 或哈希表进行查找(不会比这更有效),内部条件需要 O(n)
:
while(queue is not empty){
for(i looping from 0 to the size of the queue){
curr = the first element in the queue;
if curr is endWord, then returns level + 1;
for(j starting from 0 to the length of curr){
for(c starting from a to z){
O(n)
}
}
}
}
下一个最里面的循环迭代了26次,所以还是O(n)
:
while(queue is not empty){
for(i looping from 0 to the size of the queue){
curr = the first element in the queue;
if curr is endWord, then returns level + 1;
for(j starting from 0 to the length of curr){
O(n)
}
}
}
下一个循环遍历字符串的长度,所以又是 n
步。额外的步骤要么是恒定时间的,要么是线性的(O(n)
),所以我们可以忽略它们:
while(queue is not empty){
for(i looping from 0 to the size of the queue){
O(n ^ 2)
}
}
这个 for 循环现在完全没用了。我们可以简单地删除它,而不是直接在 while
循环中轮询队列。 while
循环采用 O(m)
步,其中 m
是单词列表中的单词数。所以总的时间复杂度是 O(n^2 * m)
.