解法一的问题在于计算复杂的大整数除法运算,而解法二虽然将大整数的除法运算转换成了减法运算,降低了计算的复杂性,但迭代次数太多。
如果y=k*y1, x=k*x1.那么有f(y,x)=k*f(y1,x1)。
如果x=p*x1,假设p是素数,并且y不能被p整除,那么f(x,y)=f(p*x1,y)=f(x1,y)。
取p=2
若x,y均是偶数,f(x,y)=2*f(x>>1,y>>1);
若x为偶数,y为奇数,f(x,y)=f(x>>1,y);
若x为奇数,y为偶数,f(x,y)=f(x,y>>1);
若x,y均是奇数,f(x,y)=f(y,x-y).
时间复杂度为O(log(max(x,y))。
//求最大公约数的几种方法
#include <stdio.h>
bool IsEven(int x)
{
if((x & 0x1) == 0)
{
return true;
}
return false;
}
int gcd0(int x, int y) //方法一使用大量取余运算
{
return (!y) ? x : gcd0(y, x % y);
}
int gcd1(int x, int y) //方法二可能迭代次数过多
{
if(x < y)
{
return gcd1(y, x);
}
if(y == 0)
{
return x;
}
else
{
return gcd1(x - y, y);
}
}
int gcd2(int x, int y) //方法三使用位运算,效率更高
{
if(x < y)
return gcd2(y, x);
if(y == 0)
return x;
else
{
if(IsEven(x))
{
if(IsEven(y))
{
return (gcd2(x >> 1, y >> 1) << 1);
}
else
{
return gcd2(x >> 1, y);
}
}
else
{
if(IsEven(y))
{
return gcd2(x, y >> 1);
}
else
return gcd2(y, x - y);
}
}
}
int main()
{
int x = 12;
int y = 8;
printf("第一种:%d\t,第二种:%d\t,第三种:%d\t", gcd0(x, y), gcd1(x, y), gcd2(x, y));
return 0;
}