问题是这样的:
给定一个英语字典(实现为散列映射(word - >含义))和不带空格的字符串,输出有效英语单词的所有可能组合,当组合时,重现输入字符串。
这个问题可以通过递归/动态编程解决,但在分析时间复杂度时,我很困惑:
想象一下字典包含每个可能的字符排列(每个字符序列都是一个有效字),然后给出字符串,对于2个字符之间的每个位置,你可以选择是否插入一个空格,有n-1个这样的位置,所以有2 ^(n-1)个可能的结果。生成这些结果的任何算法的复杂性必须至少为O(2 ^ n)。
我可以使用动态编程算法来执行此操作。假设result [i]是子串i..N的可能分裂,以计算结果[j]:
for k in range j+1 to N:
if s[j:k] is a valid word:
merge the word in the result[k]
由于我们将结果[N]计算回结果[0],并且这些计算中的每一个都采用O(N)(因为我们依赖的子问题已被计算),时间复杂度应为O(N ^ 2)
为什么我可以从两种推理中得出不同的结论,哪些是正确的?
答案 0 :(得分:3)
除了输入字符串n
的大小之外,还应引入一个表示结果大小的附加参数r
,并在分析中使用它。在这种情况下,“结果的大小”类似于每个有效组合中单词数量的总和。
在您对算法的描述中,您将了解如何在循环体中合并中间结果。您隐含地假设这可以在恒定时间内完成。但是,正如您所指出的那样,这会导致相互矛盾的结果。
如果将算法分为两个阶段,分析会更简单:
在阶段I中,您构建一个数据结构,指示可以在字符串中嵌入单词的位置。这可以在Θ(n^2)
时间内完成,假设您可以检查每个子字符串是否是在分摊的常量时间内的单词。
在阶段II中,您遍历此数据结构以输出单词组合列表。这可以在输出大小的线性时间内完成Θ(r)
。
因此总的来说,这个算法的时间复杂度为Θ(n^2 + r)
。
注意:要正式更正,您还应该考虑阅读英文单词列表所需的时间。如果您想对此进行说明,则可以引入其他变量d
并在时间复杂度中添加+ d
字词。
另外:通过使用Aho-Corasick algorithm查找所有匹配的子字符串而不是在哈希表中查找每个子字符串,可以改进此边界的n^2
部分。 / p>