最大公约数的三种算法(欧几里得递归算法、连续整数检测算法、公共质因数相乘算法)

 最大公约数的算法在编程中是比较典型的,常见的有三种,按效率高低分别为:欧几里得递归算法、连续整数检测算法、公共质因数相乘算法。如下:

(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;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值