素数算法的复杂度

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)。

以上是关于素数算法的复杂度的主要内容,如果未能解决你的问题,请参考以下文章

算法素数专题

素数判定算法 MILLER RABIN

浅谈Miller-Rabin素数检测算法

Miller-Rabin?素数测试算法

算法优化分析---打印素数

筛素数算法——线性筛素数算法