求最大公约数

27 篇文章 0 订阅

1、辗转相除法

这条算法基于一个定理:两个正整数 a 和 b ( a > b),它们的最大公约数等于 a 除以 b 的余数 c 和 b 之间的最大公约数。
例如 10 和 25,25 除以 10 商 2 余 5,那么 10 和 25 的最大公约数,等同于 10 和 5 的最大公约数。
    public int getGreatestCommonDivisor(int a,int b){
        int big = a > b ? a:b;
        int small = a < b ? a : b;

        if(big % small == 0){
            return small;
        }

        return getGreatestCommonDivisor(big % small,small);
    }

缺点:当2个数都比较大的时候,取模操作的性能会比较差。

2、 更相减损术


原理:两个正整数 a 和 b (a>b),它们的最大公约数等于 a - b 的差值 c 和较小数 b 的最大公约数。例如 10 和 25,25 减 10 的差是15,那么 10 和 25 的最大公约数,等同于 10 和 15 的最大公约数。
    public int getGreatestCommonDivisor(int a,int b){

        if(a == b){
            return a;
        }

        int big = a > b ? a:b;
        int small = a < b ? a : b;
        return getGreatestCommonDivisor(big-small,small);
    }

缺点:当两数相差较大,如1和99999,则递归次数远大于辗转相除法,是个不稳定的算法。

3、在更相减损术的基础上使用移位运算


当 a 和 b 均为偶数时,gcd(a,b) = 2 × gcd(a/2,b/2) =2 × gcd(a≫1,b≫1)。

当 a 为偶数,b 为奇数时,gcd(a,b)=gcd(a/2,b)=gcd(a≫1,b)。

当 a 为奇数,b 为偶数时,gcd(a,b)=gcd(a,b/2)=gcd(a,b≫1)。

当 a 和 b 均为奇数时,先利用更相减损术运算一次,gcd(a,b) = gcd(b,a−b), 此时 a-b 必然是偶数,然后又可以继续进行移位运算。

例如计算 10 和 25 的最大公约数的步骤如下。

整数 10 通过移位,可以转换成求 5 和 25 的最大公约数。
利用更相减损术,计算出 25-5=20,转换成求 5 和 20 的最大公约数。
整数 20 通过移位,可以转换成求 5和 10 的最大公约数。
整数 10 通过移位,可以转换成求 5 和 5 的最大公约数。
利用更相减损术,因为两数相等,所以最大公约数是 5。

这种方式在两数都比较小时,可能看不出计算次数的优势;当两数越大时,计算次数的减少就会越明显。

public int gcd(int a, int b){
    if(a == b){
        return a;
    }
    if((a&1)==0 && (b&1)==0){
        return gcd(a>>1, b>>1)<<1;
    } else if((a&1)==0 && (b&1)!=0){
        return gcd(a>>1, b);
    } else if((a&1)!=0 && (b&1)==0){
        return gcd(a, b>>1);
    } else {
        int big = a>b ? a:b;
        int small = a<b ? a:b;
        return gcd(big-small, small);
    }
}

1、暴力枚举法:时间复杂度是 O(min(a,b))。

2、辗转相除法:时间复杂度不太好计算,可以近似为O(log(max(a,b))),但是取模运算性能较差。

3、更相减损术:避免了取模运算,但是算法性能不稳定,最坏时间复杂度为 O(max(a,b))。

4、更相减损术与移位相结合:不但避免了取模运算,而且算法性能稳定,时间复杂度为 O(log(max(a,b)))。

作者:小灰
链接:https://leetcode-cn.com/leetbook/read/journey-of-algorithm/52c1mm/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值