最大公约数问题

牧云@^-^@ 提交于 2020-01-20 16:48:25

最大公约数问题

题目描述

如何求两个正整数的最大公约数?

思路

  1. 暴力枚举法

没什么好说的,直接看代码

    //暴力枚举法
    public static int gcd1(int a, int b){
        int big = a > b ? a : b;
        int small = a < b ? a : b;
        if (big%small==0){
            return small;
        }
        for (int i = small/2; i > 0; i--){
            if (small % i == 0 && big % i == 0){
                return i;
            }
        }
        return 1;
    }
  1. 辗转相除法

基于定理:两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数

基于这条定理,我们利用递归法就可以解决问题

    //辗转相除法
    public static int gcd2(int a, int b){
        int big = a > b ? a : b;
        int small = a < b ? a : b;
        if (big%small==0){
            return small;
        }
        return gcd2(big%small, small);
    }
  1. 更相减损术

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

同样利用递归法解决

    //更相减损术
    public static int gcd3(int a, int b){
        int big = a > b ? a : b;
        int small = a < b ? a : b;
        if (big%small==0){
            return small;
        }
        return gcd3(big-small, small);
    }
  1. 更相减损术与移位相结合

暴力枚举法时间复杂度为O(min(a,b))O(min(a, b))
辗转相除法时间复杂度近似为O(log(max(a,b)))O(log(max(a, b))),但是取模运算性能较低
更相减损术算法不稳定,最坏时间复杂度为O(max(a,b))O(max(a, b))

因此将辗转相除法和更相减损术的优势结合起来,即在更相减损术的基础上使用移位运算。具体步骤如下:
①当a和b为偶数时,gcd(a,b)=2×gcd(a/2,b/2)=2×gcd(a1,b1)gcd(a,b)=2\times gcd(a/2, b/2)=2\times gcd(a\gg 1, b\gg 1)
②当a为偶数,b为奇数时,gcd(a,b)=gcd(a/2,b)=gcd(a1,b)gcd(a,b)=gcd(a/2,b)=gcd(a\gg 1,b)
③当a为奇数,b为偶数时,gcd(a,b)=gcd(a,b/2)=gcd(a,b1)gcd(a,b)=gcd(a,b/2)=gcd(a,b\gg 1)
④当a和b均为奇数时,先利用更相减损术运算一次,gcd(a,b)=gcd(b,ab)gcd(a,b)=gcd(b,a-b),此时a-b必然是偶数,然后又可以继续利用移位运算

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

此算法不但避免了取模运算,而且算法稳定,时间复杂度为:O(log(max(a,b)))O(log(max(a,b)))

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!