最大公约数问题
题目描述
如何求两个正整数的最大公约数?
思路
- 暴力枚举法
没什么好说的,直接看代码
//暴力枚举法
public static int gcd1(int a, int b){
int big = a > b ? a : b;
int small = a < b ? a : b;
if (big%small==0){
return small;
}
for (int i = small/2; i > 0; i--){
if (small % i == 0 && big % i == 0){
return i;
}
}
return 1;
}
- 辗转相除法
基于定理:两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数
基于这条定理,我们利用递归法就可以解决问题
//辗转相除法
public static int gcd2(int a, int b){
int big = a > b ? a : b;
int small = a < b ? a : b;
if (big%small==0){
return small;
}
return gcd2(big%small, small);
}
- 更相减损术
原理:两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数
同样利用递归法解决
//更相减损术
public static int gcd3(int a, int b){
int big = a > b ? a : b;
int small = a < b ? a : b;
if (big%small==0){
return small;
}
return gcd3(big-small, small);
}
- 更相减损术与移位相结合
暴力枚举法时间复杂度为
辗转相除法时间复杂度近似为,但是取模运算性能较低
更相减损术算法不稳定,最坏时间复杂度为
因此将辗转相除法和更相减损术的优势结合起来,即在更相减损术的基础上使用移位运算。具体步骤如下:
①当a和b为偶数时,
②当a为偶数,b为奇数时,
③当a为奇数,b为偶数时,
④当a和b均为奇数时,先利用更相减损术运算一次,,此时a-b必然是偶数,然后又可以继续利用移位运算
public static int gcd4(int a, int b){
if (a==b){
return a;
}
if ((a&1)==0 && (b&1)==0){
return gcd4(a>>1,b>>1)<<1;
}else if ((a&1)==0 && (b&1)!=0){
return gcd4(a>>1, b);
}else if ((a&1)!=0 && (b&1)==0){
return gcd4(a,b>>1);
}else {
int big = a>b ? a : b;
int small = a<b ? a : b;
return gcd4(big-small, small);
}
}
此算法不但避免了取模运算,而且算法稳定,时间复杂度为:
来源:CSDN
作者:執筆、写下一塲流年
链接:https://blog.csdn.net/wy_mgl/article/details/104049555