递归运行GCD函数的时间(Euclid算法)

时间:2013-08-08 22:08:58

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

我只能找到关于如何递归和迭代地实现gcd函数的帖子,但是我找不到这个。我确信它在Stackoverflow上然而我找不到它所以我道歉如果它是一个重复的帖子。


我查看了维基百科(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)+ ???。现在分析递归调用,我不知道如何将(mod b)解释为我的递归调用以正确陈述我的递归关系。

3 个答案:

答案 0 :(得分:7)

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

如果b >= a/2然后在下一步,您将拥有a' = bb' < a/2,因为%操作将从{{1}移除b或更多}}

如果a然后在下一步,您将拥有b < a/2a' = b,因为b' < a/2操作最多可以返回%

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

答案 1 :(得分:0)

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

如果您测试上面的Euclidean GCD,那么最终会有24个递归调用。

如果您习惯于解决复发关系,您可能会对以下内容感兴趣:

enter image description here

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

答案 2 :(得分:0)

一个简单的分析和证据如下:

  1. 如果Euclid(a,b)步数超过N,则显示 a>=F(n+1)b>=F(n),其中F(i)i斐波那契 数。
    这可以通过Induction轻松完成。

  2. 再次显示F(n)≥φ n-1     诱导。

  3. 使用步骤1和2的结果,我们有b≥F(n)≥     φ n-1
    以两侧的对数为准,     log φb≥n-1。

    因此证明,n≤1+     日志<子>φ B'/ p>

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

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