最优求解最大公约数

问题:求两个整数的最大公约数

方法一:辗转相除法

原理:欧几里得算法

           两个正整数a 和 b (a > b),他们的最大公约数等于 a 除以 b 的余数 c 和 b之间的最大公约数。

代码实现:

public static int getGreatestCommonDivisorV1(int a, int b){
        int max = a > b ? a : b;
        int min = a < b ? a : b;
        if(max % min == 0){
            return min;
        }
        return getGreatestCommonDivisorV1(max % min,min);
}

辗转相除法缺点:两个整数较大时,取模运算的性能会比较差,由此引出第二种方法

 

方法二:更相减损法

原理:

两 个 正 整 数 a 和 b( a > b), 它 们 的 最 大 公 约 数 等 于 a-b 的 差 值 c 和 较 小 数 b 的 最 大 公 约 数。

递归结束条件:a = b

代码实现:

    //更相减损法
    public static int getGreatestCommonDivisorV2(int a, int b){
        int big = a > b ? a : b;
        int small = a < b ? a : b;
        if(big == small){
            return small;
        }
        return getGreatestCommonDivisorV1(big - small ,small);
    }

缺点:当两个数相差很大的时候,递归的次数就会很大,例如1000和1

 

最终版:结合两个算法

当 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 必 然 是 偶 数, 然 后 又 可 以 继 续 进 行 移 位 运 算。

代码实现:

//结合二者
    public static int getGreatestCommonDivisorV3(int a, int b) {

        if (a == b) {
            return a;
        }
        //a 为奇数, b 为偶数
        if ((a & 1) != 0 && (b & 1) == 0) {
            return getGreatestCommonDivisorV3(a, b >> 1);
        } else if ((a & 1) == 0 && (b & 1) != 0) {//a 为偶数, b 为奇数
            return getGreatestCommonDivisorV3(a >> 1, b);
        } else if ((a & 1) == 0 && (b & 1) == 0) {//a 为偶数, b 为偶数
            return getGreatestCommonDivisorV3(a >> 1, b >> 1)<<1;
        } else {
            //a 为奇数, b 为奇数
            int big = a > b ? a : b;
            int small = a < b ? a : b;
            return getGreatestCommonDivisorV3(big - small, small);
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值