编程之美7:最大公约数

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

    原文作者:勇二郎
    原文地址: https://blog.csdn.net/ndzjx/article/details/84404545
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞