1.辗转相除法
辗转相除法是平时求gcd问题最常见的解法,该解法通过将原问题转化为两个更小数的最大公约数的问题,直到其中一个数为0,剩下的另外一个数就是两者最大的公约数。
package gcd;
import java.util.*;
public class Gcd1 {
private static int gcd(int a,int b)
{
if(a%b==0)
return b;
else
return gcd(b,a%b);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int a=sc.nextInt();
int b=sc.nextInt();
System.out.println(gcd(a,b));
}
}
测试结果如下:
42 30
6
该解法的弊端便是当遇到大整数时,从而使算法的复杂度大大增加。
2.辗转相减法
当两个整数是大整数时,此时若使用辗转相除法求解的话取模运算会使复杂度大大增加。而辗转相减法可以降低大整数的时间复杂度。该算法思路是:求a,b的两个数的最大公约数,如果a大于b,则求a-b和b的最大公约数;如果a小于b,则需要交换a和b的位置;如果b等于0,则a便是最大公约数,也是递归的终止条件。
package gcd;
import java.util.Scanner;
public class Gcd2 {
private static int gcd(int a,int b)
{
if(b==0)
return a;
if(a>=b)
return gcd(a-b,b);
else
return gcd(b,a);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int a=sc.nextInt();
int b=sc.nextInt();
System.out.println(gcd(a,b));
}
}
测试结果如下:
256 576
64
该法的弊端便是增加了迭代次数,如果a和b差值悬殊,则会大大增加迭代次数。
3.综合法
辗转相除法的弊端就是不适合大整数的除法运算,而辗转相除法则使迭代次数大大增加。而综合法则是通过判断a和b两个数都为偶数则a和b都除2,并将两者最大公约数乘2;如果两者为奇数则使用辗转相减法,递归直到b=0,则a即为最大公约数。
1.a和b皆为偶数,则求a/2和b/2的最大公约数,并乘2;2.a为偶数b为奇数,则求a/2和b的最大公约数;3.a为奇数b为偶数,则求a和b/2的最大公约数;4.a和b都为奇数,则使用辗转相减法,即求a和abs(a-b)的最大公约数;5.如果其中一个值为0,则另一个值即为最大公约数。
package gcd;
import java.util.Scanner;
public class Gcd3 {
private static int gcd(int a,int b)
{
if(a<b)
return gcd(b,a);
if(b==0)
return a;
else {
if(a%2==0)
{
if(b%2==0)
return 2*gcd(a>>1,b>>1);
else
return gcd(a>>1,b);
}
else
{
if(b%2==0)
return gcd(a,b>>1);
else
return gcd(a-b,b);
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int a=sc.nextInt();
int b=sc.nextInt();
System.out.println(gcd(a,b));
}
}
测试结果如下:
42 30
6
该法则是避免了前面两种方法的弊端,并且时间复杂度也控制在O(log(max(a,b)))。