1. 程式人生 > >程式設計之美7:最大公約數

程式設計之美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