1:辗转相除法
f(x,y) = f(y, x%y);
int gcd(int x, int y)
{
return (!y) ? x : gcd(y, x % y);
}
2:对于大整数,取模运算非常昂贵。
f(x, y) = f(x-y, y);
BigInt gcd(BigInt x, BigInt y)
{
if (x < y)
{
return gcd(y, x);
}
if (y == 0)
{
return x;
}
else
{
return gcd(x-y, y);
}
}
缺点:减法的迭代次数太多
3:找规律
(1):f(y,x) = k * f(y1,x1); 其中y = k*y1, x = k*x1;
(2):f(x,y) = f(p*x1, y) = f(x1,y); 其中x=p*x1,假设p是素数,并且y%p!=0
取p = 2;
若x,y均为偶数,f(x,y) = 2*f(x/2,y/2) = 2* f(x>>1,y>>1)
若x为偶数,y为奇数, f(x,y)=f(x/2,y)=f(x>>1,y)
若x为奇数,y为偶数, f(x,y)=f(x,y/2) = f(x, y>>1)
若x,y均为奇数,f(x,y) = f(y, x-y)
那么在f(x,y)=f(y,x-y)之后,(x-y)是一个偶数,下一步一定会有除以2的操作
因此,最坏情况下时间复杂度O(log2为底(max(x,y)))。
巧妙的利用位移运算和减法运算,避开了大整数除法,提高了算法的效率。
BigInt gcd(BigInt x,BigInt y)
{
if (x < y)
{
return gcd(y, x);
}
if (y == 0)
{
return x;
}
else
{
if (IsEven(x))
{
if (IsEven(y))
{
return (gcd(x >> 1, y >> 1) << 1);
}
else
{
return gcd(x >> 1, y);
}
}
else
{
if (IsEven(y))
{
return gcd(x, y >> 1);
}
else
{
return gcd(y, x - y);
}
}
}
}
原创:https://blog.csdn.net/ndzjx/article/details/84404545