两个整数的最大公约数是能整除这两个整数的最大数。
下面给出几种算法,求两个整数和
的最大公约数。
一种是穷举法。该算法检测(k=2,3,4,等等)是否是
和
的公约数,直到
大于
或者
。该算法可以如下描述:
public static int gcd(int m,int n){
int gcd = 1;
for(int k=2;k<=m&&k<=n;k++){
if(m%k==0&&n%k==0)
gcd=k;
}
return gcd;
}
假设
是否还有更好的算法呢?不是从1开始查找可能的除数,而是从开始向下查找,这样效率会更高。一旦找到一个除数,该除数就是最大公约数。
public static int gcd(int m,int n){
int gcd = 1;
for(int k=n;k>=1;k--){
if(m%k==0&&n%k==0)
gcd=k;
break;
}
return gcd;
}
这个算法比之前的一个效率更高,但是它的最坏情况的时间复杂度依旧是。
其实,我们还可以知道,数字n的除数不可能比大;因此可进一步提高算法效率;但是仅仅考虑到k至多是
或
的1/2是不够的,因为
可能会是
的除数,于是算法可以如下表示:
public static int gcd(int m, int n) {
int gcd = 1;
if (m % n == 0)
return n;
for (int k = n / 2; k >= 1; k++) {
if (m % k == 0 && n % k == 0) {
gcd = k;
break;
}
}
return gcd;
}
假设,那么这个for循环最多执行n/2次,只是前一个算法的一半。该算法的时间复杂度仍然是
。
求最大公约数的一个更有效的方法是在公元前300年作于由进欧几里得发现的,这是最古老的著名算法之一。他可以递归的定义为:
用表示整数m和n的最大公约数:
如果为0;那么
为
。
否则,就是
。
不难证明这个算法的正确性。假设,那么,
,这里的
是
的商。能整除
和
的任意数字都必须也能整除
。因此,
和
是一样的,其中
。该算法的实现程序如下:
public static int gcd(int m,int n){
if(m%n==0)
return n;
else
return gcd(n,m%n);
}
最好的情况是当