Time complexity of Euclid's Algorithm
我很难确定欧几里得最大公分母算法的时间复杂性是什么。该伪码算法为:
1 2 3 4 5 6 | function gcd(a, b) while b ≠ 0 t := b b := a mod b a := t return a |
这似乎取决于a和b。我的想法是时间复杂性是o(a%b)。对吗?有没有更好的方法来写呢?
分析欧几里得算法的时间复杂性的一个技巧是遵循两次迭代的结果:
1 | a', b' := a % b, b % (a % b) |
现在A和B都会减少,而不是只减少一个,这使得分析更容易。您可以将其分为以下几种情况:
- 小A:
2a <= b 。 - 小B:
2b <= a 。 - 小A:
2a > b ,但a < b 。 - 小B:
2b > a ,b < a 。 - 相等:
a == b 。
现在我们将显示,每一个案例至少减少了四分之一的EDOCX1×11的总数:
- 微小A:
b % (a % b) < a 和EDCX1〔4〕,因此b 至少减少一半,因此EDCX1〔11〕至少由25% 减少。 - 微小B:
a % b < b 和EDCX1〔5〕,因此a 至少减少一半,因此EDCX1〔11〕至少由25% 减少。 - 小A:
b 将成为b-a ,这比EDCX1〔24〕小,EDOCX1×11〕至少通过EDCX1〔16〕减小。 - 小B:
a 变为a-b ,小于a/2 ,至少减少a+b 。 - 相等:
a+b 下降到0 ,明显减少a+b ,至少减少25% 。
因此,通过案例分析,每两步至少使
1 2 3 4 5 6 7 8 | (4/3)^S <= A+B S <= lg[4/3](A+B) S is O(lg[4/3](A+B)) S is O(lg(A+B)) S is O(lg(A*B)) //because A*B asymptotically greater than A+B S is O(lg(A)+lg(B)) //Input size N is lg(A) + lg(B) S is O(N) |
所以迭代次数在输入位数上是线性的。对于适合于CPU寄存器的数字,可以将迭代建模为占用恒定时间,并假设GCD的总运行时间是线性的。
当然,如果处理的是大整数,那么必须考虑到每个迭代中的模运算没有固定的成本。粗略地说,总的渐近运行时间是多对数因子的n^2倍。有点像
分析算法的合适方法是确定其最坏情况。欧几里得GCD的最坏情况发生在涉及斐波那契对时。
例如,让我们选择股息是55,除数是34的情况(记住,我们仍在处理斐波那契数)。
正如您可能注意到的,这个操作花费了8次迭代(或递归调用)。
让我们试试更大的斐波那契数,即121393和75025。我们在这里也可以注意到它花费了24次迭代(或递归调用)。
您还可以注意到,每个迭代都会产生一个斐波那契数。所以我们有这么多的行动。我们不能只用斐波那契数来获得类似的结果。
因此,时间复杂性将由小的oh(上界)表示,这次。下界是直观的ω(1):例如500除以2。
我们来解递推关系:
我们可以说,欧几里德GCD最多可以进行log(XY)操作。
在维基百科的文章中有一个很好的视角。
对于值对,它甚至有一个很好的复杂度图。
不是
众所周知,它所采取的步骤永远不会超过较小数字位数的五倍。因此,最大步数随着位数的增加而增加。每一步的成本也随着位数的增加而增加,因此复杂性受
请看这里。
尤其是本部分:
Lamé showed that the number of steps needed to arrive at the greatest common divisor for two numbers less than n is
因此,
这是对欧几里得算法运行时复杂性的直观理解。正式的证明包含在各种文本中,如算法介绍和TAOCP第2卷。
首先考虑一下,如果我们尝试用两个斐波那契数f(k+1)和f(k)的gcd。您可能会很快观察到欧几里得算法迭代到f(k)和f(k-1)。也就是说,每次迭代,我们在斐波那契级数中向下移动一个数字。由于斐波那契数是O(phi^k),其中phi是黄金比率,我们可以看到gcd的运行时间是O(log n),其中n=max(a,b),logs以phi为基数。接下来,我们可以通过观察斐波那契数持续产生对来证明这是最坏的情况,其中余数在每次迭代中保持足够大,并且直到到达系列的开始时才变为零。
我们可以使o(log n)中n=max(a,b)的界限更紧。假设b>=a,这样我们就可以在o(logb)处写入绑定。首先,观察gcd(ka,kb)=gcd(a,b)。由于k的最大值是gcd(a,c),我们可以在运行时用b/gcd(a,b)替换b,从而使o的界限更为严格(logb/gcd(a,b))。
欧几里德算法的最坏情况是,在每一步中,余数是最大的,即对于斐波那契序列的两个连续项。
当n和m是a和b的位数时,假设n大于等于m,则算法使用o(m)除法。
请注意,复杂性总是根据输入的大小给出的,在这种情况下是数字的数量。
当n和m都是连续的斐波那契数时,会出现最坏的情况。
GN(FN,FN?1)=GCD(FN?1,FN?2)=?=gcd(f1,f0)=1,第n个fibonacci数为1.618^n,其中1.618是黄金比率。
因此,为了找到gcd(n,m),递归调用的数量将是完成(logn)。
然而,对于迭代算法,我们有:
1 2 3 4 5 6 7 8 9 10 11 12 13 | int iterativeEGCD(long long n, long long m) { long long a; int numberOfIterations = 0; while ( n != 0 ) { a = m; m = n; n = a % n; numberOfIterations ++; } printf(" Iterative GCD iterated %d times.", numberOfIterations); return m; } |
对于fibonacci对,
1 2 3 4 5 6 7 8 9 10 11 12 13 | int iterativeEGCDForWorstCase(long long n, long long m) { long long a; int numberOfIterations = 0; while ( n != 0 ) { a = m; m = n; n = a - n; numberOfIterations ++; } printf(" Iterative GCD iterated %d times.", numberOfIterations); return m; } |
是的,对于斐波那契对,
我们也知道,在之前对同一问题的回答中,有一个主要的递减因素:
因此,为了以定义的形式形成欧几里得GCD的迭代版本,我们可以将其描述为"模拟器",如下所示:
1 2 3 4 5 6 7 8 9 10 | void iterativeGCDSimulator(long long x, long long y) { long long i; double factor = x / (double)(x % y); int numberOfIterations = 0; for ( i = x * y ; i >= 1 ; i = i / factor) { numberOfIterations ++; } printf(" Iterative GCD Simulator iterated %d times.", numberOfIterations); } |
根据Jauhar Ali博士的工作(最后一张幻灯片),上面的循环是对数的。
是的,小哦,因为模拟器最多能告诉迭代次数。在欧几里得GCD上进行研究时,非斐波那契对的迭代次数比斐波那契少。
Gabriel-Lame定理用对数(1/sqrt(5)*(a+1/2))-2限制步数,其中对数的基数是(1+sqrt(5))/2。这是针对算法的最坏情况场景,当输入是连续的Fibanocci数时会发生。
稍微宽松一点的界限是:log a,其中日志的基(sqrt(2))由koblitz隐含。
出于密码的目的,我们通常考虑算法的位复杂性,考虑到比特大小近似由k=Loga给出。
下面是Euclid Algorith的位复杂度的详细分析:
虽然在大多数文献中,O(Loga)^ 3给出欧几里德算法的位复杂度,但存在一个更严格的界限,即O(Loga)^ 2。
考虑;r0=a,r1=b,r0=q1.r1+r2。…,ri-1=qi.ri+ri+1,……,rm-2=qm-1.rm-1+rm rm-1=qm.rm
观察:a=r0>=b=r1>r2>r3…>rm-1>rm>0………(1)
Rm是a和b的最大公约数。
根据Koblitz的书(数论和密码学课程)中的一个主张,可以证明:ri+1<(ri-1)/2……………(2)
在Koblitz中,将k位正整数除以l位正整数所需的位操作数(假设k>=l)被给出为:(k-l+1).l………(3)
通过(1)和(2)除数是O(loga),因此通过(3)总的复杂性是O(loga)^3。
现在,这可能会减少到O(loga)^2在koblitz的评论。
考虑Ki=logri+1
通过(1)和(2)我们得到:对于i=0,1,…,m-2,m-1和ki+2<=(ki)-1对于i=0,1,…,m-2
并且由(3)m除数的总成本以:和[(ki-1)-((ki-1))]*ki为界,i=0,1,2,…,m
重新排列:总和[(ki-1)-((ki-1))]*ki<=4*k0^2
所以欧几里得算法的位复杂性是O(loga)^2。