欧几里得算法
Euclidean Algorithm
注:《数据结构与算法分析——Java语言描述》Mark Allen Weiss 第二章 提到欧几里得算法及其复杂度。
1. 证明
a)首先证明 gcd(a,b) = gcd(b,a mod b)
充分性:
a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个公约数,则有
d|a, d|b,而r = a - kb,因此d|r
因此d是(b,a mod b)的公约数
必要性:
假设d 是(b,a mod b)的公约数,则
d | b , d |r ,但是a = kb +r
因此d也是(a,b)的公约数
综上,(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证。
b)补充说明:当gcd(a,b) = gcd(b, a mod b) = ... = gcd(x, 0) = x (x!=0)
由于0和其他非零整数的最大公约数就是该非零整数,由gcd(a,b)推演gcd(x,0)的过程就是计算最大公约数的过程。
2. 递归实现
int gcd(int a, int b) {
if(b == 0) return a;
return gcd(b, a % b);
}
3. 非递归实现
int gcd(int a, int b) {
int r;
while(b != 0) {
r = a % b;
a = b;
b = r;
}
return a;
}
4. 算法复杂度分析
对于任意两个数a,b满足a > b;
• 如果 b ≤ a/2 ,则 amod b ≤ b ≤ a/2
• 如果 b > a/2 ,则 a mod b ≤ a – b ≤ a – a/2 ≤a/2
可以看出每次这个操作都会将a减半,所以最后复杂度是O(log n)。
5. 改进算法 Stein算法
Stein算法由J. Stein 1961年提出,这个方法也是计算两个数的最大公约数。
和欧几里德算法不同的是,Stein算法只有整数的移位和加减法,这对于程序设计者是一个福音。
参考网址:
http://blog.csdn.net/pinganzi/article/details/8031289
http://www.cnblogs.com/Cmpl/archive/2011/05/28/2060582.html