【问题标题】:Running Time of GCD Function Recursively (Euclid Algorithm)GCD函数递归运行时间(欧几里得算法)
【发布时间】:2013-08-10 19:33:25
【问题描述】:

我只能找到有关如何递归和迭代地实现 gcd 函数的帖子,但是我找不到这个。我确定它在 Stackoverflow 上,但是我找不到它,所以如果它是重复的帖子,我深表歉意。


我在 Wikipedia (here) 上查看了分析,无法理解它们的重复关系。

考虑以下在 C 中递归实现的 GCD 函数的实现。它的前提条件是两个数字都必须是正数,但与运行时间无关。

int gcd( int const a, int const b ) {
  // Checks pre conditions.
  assert( a >= 0 );
  assert( b >= 0 );

  if ( a < b ) return gcd( b, a );

  if ( b == 0 ) return a;

  return gcd( b, a % b );
}

对运行时间进行分析,我发现每个操作都是 O(1),因此我们知道到目前为止的递归关系是:T(n) = O(1) + ???。现在来分析递归调用,我不确定如何将 a (mod b) 解释为我的递归调用以正确说明我的递归关系。

【问题讨论】:

标签: c runtime time-complexity recurrence greatest-common-divisor


【解决方案1】:

在每个递归步骤中,gcd 会将其中一个参数减半(最多)。要看到这一点,请查看以下两种情况:

如果是b &gt;= a/2,那么在下一步您将拥有a' = bb' &lt; a/2,因为% 操作将从b 或更多a 中删除。

如果b &lt; a/2,那么在下一步你将拥有a' = bb' &lt; a/2,因为% 操作最多可以返回b - 1

因此,在每个递归步骤中,gcd 将其中一个参数减半(最多)。这是 O(log(N)) 步,其中 N 是初始 ab 的最大值。

【讨论】:

    【解决方案2】:

    要分析欧几里得 GCD,您应该使用斐波那契对:gcd(Fib[n], Fib[n - 1]) - 最坏情况。

    如果你在上面测试你的欧几里得 GCD,你最终会得到 24 个递归调用。

    如果您习惯于递归关系求解,您可能会对以下内容感兴趣:

    通过这项研究,我们无法推断出任何被除数/除数对的确切迭代次数(因此使用了小的 Oh 符号),但它保证了这个上限是有效的。 通常,下限为 Omega(1)(例如当除数为 1 时)。

    【讨论】:

      【解决方案3】:

      简单的分析证明如下:

      1. 表明如果 Euclid(a,b) 的步数超过 N 步数,则 a&gt;=F(n+1)b&gt;=F(n),其中 F(i)ith 斐波那契 数字。
        这可以通过归纳轻松完成。

      2. 显示F(n) &geq; φn-1,再次由 感应。

      3. 使用第 1 步和第 2 步的结果,我们有 b &geq; F(n) &geq; φn-1
        两边取对数, logφb &geq; n-1。

        因此证明,n &leq; 1+ 日志φb


      这个界限可以改进。
      EUCLID(ka,kb) 中的递归调用次数与 EUCLID(a,b) 中的相同,其中 k 是某个整数。

      因此,边界改进为 1 + logφ( b / gcd(a,b) )。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-02
        • 2020-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多