素数算法的复杂度
Posted
技术标签:
【中文标题】素数算法的复杂度【英文标题】:Complexity of prime factor algorithm 【发布时间】:2015-10-09 19:09:14 【问题描述】:我刚刚研究了如何使用this 算法找到一个数的质因数,该算法基本上是这样工作的:
void printPrimeFactors(N)
while N is even
print 2 as prime factor
N = N/2
// At this point N is odd
for all the ODDS i from 3 to sqrt(N)
while N is divisible by i
print i as prime factor
N = N / i
if N hasn't been divided by anything (i.e. it's still N)
N is prime
一切都很清楚,但是我不确定如何计算上述程序的 big-O 复杂度。
作为最昂贵的操作(我想),我会说,作为最坏的情况,最多可能有 log(N) 个除法,但我并不完全确定这一点。
【问题讨论】:
我会说可分割的检查是主要因素,最坏的情况是当 N 是素数时。这意味着您执行sqrt(N)
检查,所有这些都返回错误。
好点,现在你让我想到了。 O(sqrt(N)) 似乎比我想象的更合理
@biziclop,这个特定的算法是 O(sqrt(N))。然而,该算法远非最优。例如,在ODDS i
的主循环中,您可以在每次成功迭代时将上限从sqrt(N)
减少到sqrt(N / product of known factors)
。我建议在实施之前研究“筛子”和相关算法。
@Michael 你说得对,我认为随着N
的更新,上限也会下降。当然,即使您仔细调整界限,即使您跳过已知的合数(将算法变成基本的 Erathothenes 筛法),该算法仍远未达到最佳状态
【参考方案1】:
您可以像这样继续。首先,我们只对N
非常大时应用程序的行为感兴趣。在这种情况下,我们可以简化很多:如果两个部分具有不同的渐近性能,我们只需要取表现最差的那个。
第一个while
最多可以循环m
次,其中m
是最小整数,因此2m >= N
。因此,在最坏的情况下,它将循环 log2N
次——这意味着它执行为 O(log N
)。请注意,当N
足够大时,日志类型无关紧要。
for
循环运行 O(sqrt N
) 次。在规模上,这比日志N
要大得多,所以我们可以删除日志。
最后,我们需要评估循环内的while
。由于这个 while 循环只对除数执行,所以它将有一个大 O 等于它们的数量。稍加思考我们可以看到,在最坏的情况下,while
将循环 log3N
次,因为 3 是可能的最小除数。
因此,while 循环仅被执行 O(log N
) 次,但外部 for
被执行 O(sqrt N
) 次(并且通常 while 循环不会运行,因为当前数字不会分裂)。
总之,耗时最长的部分是for
循环,这将使算法变为 O(sqrtN
)。
【讨论】:
很好的解释。 Small nitpick:除法的次数在O(sqrtN
),但算法的运行时复杂度更差,因为大数的除法> O(1)。以上是关于素数算法的复杂度的主要内容,如果未能解决你的问题,请参考以下文章