zoukankan      html  css  js  c++  java
  • 求最大公约数

    求解两数的最大公约数有以下四种常见的方法:

    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>1;i--){
                if(small%i == 0 && big % i == 0){
                    return i;
                }
            }
            return 1;
        }

    2.辗转相除法

     /**
         * 辗转相除法
         *
         * 这条算法基于一条定理,两个正整数a,b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数
         * 例如:10和25,25除以10商2余5,那么10和25的最大公约数等同于10和5的最大公约数。
         * 有了这条定理我们求最大公约数就变得简单。我们可以使用递归的方法把问题逐步简化
         * 首先,计算出a除以b的余数c,把问题简化成b和c的最大公约数;然后计算出b除以c的余数d,把问题转化成求c和d的最大公约数....
         * 以此类推,逐渐把两个较大整数之间的运算简化成两个较小整数之间的运算,直到两个数可以整除,或者其中一个数减小到1为止
         * @param a
         * @param b
         * @return
         */
        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);
        }

    3..更相减损术

     /**
         * 更相减损术
         *
         * 这条算法基于一条定理,两个正整数a,b(a>b),求它们的最大公约数等于a-b的差值c和b之间的最大公约数
         * 例如:10和25,25-10 = 15,那么10和25的最大公约数等同于10和15的最大公约数。
         * 有了这条定理我们求最大公约数就变得简单。我们可以使用递归的方法把问题逐步简化
         * 首先,计算出a-b的差值c,把问题简化成b和c的最大公约数;然后计算出b-c的差值d,把问题转化成求c和d的最大公约数....
         * 以此类推,逐渐把两个较大整数之间的运算简化成两个较小整数之间的运算,直到两个数相等,最大公约数就是最终两者相等的值
         *
         * @param a
         * @param b
         * @return
         */
        public static int gcd3(int a,int b){
            if(a == b) return a;
            int big = a>b?a:b;
            int small = a<b?a:b;
    
            return gcd2(big-small,small);
        }

    4.更相减损术与移位相结合

    /**
         * 更相减损术与移位相结合
         * 
         * 当a,b都为偶数时,gcd(a,b) =  2 * gcd(a/2,b/2) = gcd(a>>1,b>>1)<<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都为奇数时(a>b),先利用更相减损术运算一次gcd(a,b) = gcd(a-b,b),此时a-b必然是偶数,然后又可以利用移位运算
         * 例如计算10和25的最大公约数的步骤如下:
         * 1.整数10通过移位,可以转换成求5和25的最大公约数
         * 2.利用更相减损术,计算25-5 = 20,转换成求5和20的最大公约数
         * 3.整数20通过移位,可以转换成1求10和5的最大公约数
         * 4.整数10通过移位,可以转换成求5和5的最大公约数
         * 5.利用更相减损术,以为两数相等,所以最大公约数是5
         *
         * @param a
         * @param b
         * @return
         */
        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 gcd2(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)))

  • 相关阅读:
    GitLab 介绍
    git 标签
    git 分支
    git 仓库 撤销提交 git reset and 查看本地历史操作 git reflog
    git 仓库 回退功能 git checkout
    python 并发编程 多进程 练习题
    git 命令 查看历史提交 git log
    git 命令 git diff 查看 Git 区域文件的具体改动
    POJ 2608
    POJ 2610
  • 原文地址:https://www.cnblogs.com/du001011/p/10822122.html
Copyright © 2011-2022 走看看