最大公约数的算法在编程中是比较典型的,常见的有三种,按效率高低分别为:欧几里得递归算法、连续整数检测算法、公共质因数相乘算法。如下:
(1)欧几里得递归算法:
第一步:如果n=0;返回m值作为结果,同时过程结束;否则进入第二步。
第二步:m除以n,将余数赋给r。
第三步:将n的值赋给m,将r的值赋给n,返回第一步。
代码描述如下:
public static int gcd1(int m,int n){
if(m < n){
int temp = m;
m = n;
n = temp;
}
if(n == 0)
return m;
else
return gcd1(n,m%n);
}
(2)连续整数检测算法:
第一步:将min{m,n}的最小值赋给t
第二步:m除以t,如果余数为0,进入第三步;否则进入第四步
第三步:n除以t,如果余数为0,返回t的值作为结果;否则进入第四步
第四步:把t的值减1,返回第二步。
代码描述如下:
public static int gcd2(int m,int n){
int t;
if(m < n)
t = m;
else
t = n;
for(t = n;t >= 1; t--){
if(m%t==0 & & n%t==0)
break;
}
return t;
}
这两种算法的代码很简洁,而且效率也很高,所以在任何一种编程语言中都有他们两个的身影,但是很少见到第三种的描述。我记得我们在小学学习最大公约数的时候不是用这两种方法的,而是第三种。比如说求24和18的最大公约数— —
24 = 2 * 2 * 2 * 3
18 = 2 * 3 * 3
所以,最大公约数为:2 * 3 =6,看起来很容易的,可是用代码写出来却很复杂。今天做了一下这个费劲不讨好的算法。先描述一下吧:
(3)公共质因数相乘算法:
第一步:找出m的所有质因数
第二步:找出n的所有质因数
第三步:找出m和n的所有公因数(如果p是一个公因数,而且在m和n的质因数分解式中 分别出现p和q次,那么将p重复min{p,q}次)
第四步:将所有公共质因数相乘,结果返回。
代码描述如下(分三步走):
(1)找出n以内(包括n)的所有质数,结果存在一个List中
public static List< Integer> primeList(int n){
List< Integer> prime = new ArrayList< Integer>();
//将2-n之间的所有自然数放进List.
for(int i = 2;i
prime.add(i);
int end = (int)Math.sqrt(n);
//将非质数从Llist中去掉
for(int i = 2; i
if(prime.indexOf(i) == -1)
continue;
for(int j = prime.indexOf(i)+1; j < prime.size(); j++){
if(prime.get(j)%i == 0)
prime.remove(j);
}
}
return prime;
}
(2)找出正整数n的所有质因数,放进一个List中
public static List< Integer> primeDivisorList(int n){
List< Integer> prime = primeList(n/2);//只需要前n/2个质数
List< Integer> primeDivisor = new ArrayList< Integer>();
int i = 0;
while(true){
if(n == 1)break;
if(n%prime.get(i) == 0){
primeDivisor.add(prime.get(i));
n = n/prime.get(i);
i = 0;//因为一个数可以有多个相同的质因数,所以要再从头寻找
}
else
i++;
}
return primeDivisor;
}
(3)找出公因数相乘,求两个数的最大公约数
public static int gcd3(int m,int n){
int result = 1;
List< Integer> mList = primeDivisorList(m);
List< Integer> nList = primeDivisorList(n);
while(!mList.isEmpty() & & !nList.isEmpty()){
int i;
for(i = 0;i < nList.size();i++){
if(mList.get(0) == nList.get(i)){
//每找到一个公因数,将该数从两个公因数列表中删除
mList.remove(i);
result = result * nList.remove(i);
break;
}
}
if(i == nList.size())
if(!mList.isEmpty())
mList.remove(0)
}
return result;
}