求最大公约数算法

自己看相关算法的时候看到求两个数的最大公约数的算法,所以想总结一下关于这方面的知识。
欧几里得算法:欧几里得算法算是求最大公约数最经典的算法,其基于的思想是,对于 gcd(a,b) a>b ,设a,b的最大公约数是d,则:
(1) r=akb ,a能被d整除,b也能被d整除,所以r也能被d整除;
(2) gcd(a,b) 则可以转化为 gcd(b,r) ,这里 r=akb 即就是 a%b
该算法可以用递归实现,递归的终止条件是 a%b=0 ,其返回值为a,就是最大公约数。

    int gcd1(int a, int b){
        if(a<b){
            int temp = b;
            b = a;
            a = temp;
        }
        if(b == 0){
            return a;
        }
        return gcd1(b, a%b);
    }

还有一种非递归的写法:

    //求最大公约数-欧几里得算法-非递归写法
    int gcd2(int a, int b){
        if(a<b){
            int temp = b;
            b = a;
            a = temp;
        }
        while(b != 0){
            int temp = b;
            b = a%b;
            a = temp;
        }
        return a;
    }

尼考曼彻斯法:假设 (a,b) 的最大公约数为T,则假设 a=mT,b=nT ,则a,b不断相减就可以在最后就只剩下一个T,则这个T就是最大公约数。

    //尼考曼彻斯法-更相减损法
    int gcd3(int a, int b){
        if(a<b){
            int temp = b;
            b = a;
            a = temp;
        }
        while(a - b != 0){
            int temp = b;
            b = a -b;
            a = temp;
        }
        return a;
    }

Stein算法:该算法是建立在以下几个知识点的基础之上
(1) gcd(a,a) 的最大公约数还是a;
(2) gcd(ka,kb)=kgcd(a,b)
(3)如果a是奇数,b是偶数, gcd(a,b)=gcd(a,b/2) ,反之亦成立。

    int gcd4(int a, int b){
        if(a<b){
            int temp = b;
            b = a;
            a = temp;
        }
        if(0 == b) 
            return a;
        //如果a,b是偶数
        if(((a&1) == 0) && ((b&1) == 0)){
            return 2*gcd4(a>>1, b>>1);
        }
        //如果a是偶数,b是奇数
        if(((a&1) == 0) && ((b&1) != 0)){
            return gcd4(a>>1, b);
        }
        //如果a是奇数,b是偶数
        if(((a&1) != 0) && ((b&1) == 0)){
            return gcd4(a, b>>1);
        }
        //如果a,b是奇数
        if(((a&1) != 0) && ((b&1) != 0)){
            return gcd4(b, (a - b)>>1);
        }
    }

还有一种写法:

int gcd(int x,int y)   
{
        int i,j;
        if(x==0) return y;
        if(y==0) return x;
        for(i=0;0==(x&1);++i)x>>=1;   // 去掉所有的2
        for(j=0;0==(y&1);++j)y>>=1;   // 去掉所有的2
        if(j<i) i=j;
        while(1){
                if(x<y)x^=y,y^=x,x^=y;   // 若 x < y 交换 x, y
                if(0==(x-=y)) return y<<i;  // 若x == y, gcd == x == y (就是在辗转减,while(1)控制)
                while(0==(x&1))x>>=1; // 去掉所有的2
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值