求两个整数的最大公约数,要尽量优化算法的性能


求两个整数的最大公约数,要尽量优化算法的性能

 

思路:

  方法一 辗转相除法, 两个正整数a,b(a>b), 它们的最大公约数 = a除以b的余数c和较小数b之间的最大公约数。

       例如:10和25, 25除以10=2...5, 那么10和25的最大公约数, 等同于10和余数5的最大公约数。

  方法二:更相减损术 两个正整数a,b(a>b), 它们的最大公约数 = a-b的差值c和较小数b之间的最大公约数。

      例如:10和25, 25-10=15, 那么10和25的最大公约数, 等同于10和15的最大公约数。

  两个整数较大时候的场景,取模性能会比较差,更相减损术更适合。但如果两个数相差悬殊,比如10000和1时,更相减损术就要递归9999次。此时可以用方法三

  方法三: 更相减损术+移位(最优):

  1. 当a,b均为偶数时,gcd(a,b) = 2*gcd(a/2,b/2) = 2*gcd(a>>1,b>>1),gcd为方法名;
  2. 当a为偶数,b为奇数时,gcd(a,b) = gcd(a/2,b) = gcd(a>>1,b);
  3. 当a为奇数,b为偶数时,gcd(a,b) = gcd(a,b/2) = gcd(a,b>>1);
  4. 当a,b均为奇数,先使用更相减损术运算一次,gcd(a,b) = gcd(b,a-b),此时a-b必然是偶数,然后又可以继续进行移位运算 

    ps. >>相当于除以2,<<相当于乘以2

 代码实现:

/**
 * 求两个整数的最大公约数,要尽量优化算法的性能
 *
 * 方法一:辗转相除法, 两个正整数a,b(a>b), 它们的最大公约数 = a除以b的余数c和较小数b之间的最大公约数。
 *      例如:10和25, 25除以10=2...5, 那么10和25的最大公约数, 等同于10和余数5的最大公约数。
 * 方法二:更相减损术, 两个正整数a,b(a>b), 它们的最大公约数 = a-b的差值c和较小数b之间的最大公约数。
 *     例如:10和25, 25-10=15, 那么10和25的最大公约数, 等同于10和15的最大公约数
 * 方法三: 更相减损术+移位
 */

public class GreatestCommonDivisor {

    /**
     * 辗转相除法
     * @param a
     * @param b
     * @return
     */
    public static int getGreatestCommonDivisor(int a, int b){
        int min = a;
        int max = b;
        if ( a >= b ){
            min = b;
            max = a;
        }
        if (min == 0){
            return max;
        }
        int p = max % min;
        return getGreatestCommonDivisor(min,p);
    }

    /**
     * 更相减损术
     * @param a
     * @param b
     * @return
     */
    public static int getGreatestCommonDivisor2(int a, int b){
        int min = a;
        int max = b;
        if ( a >= b ){
            min = b;
            max = a;
        }
        if (min == 0){
            return max;
        }
        int p = max - min;
        return getGreatestCommonDivisor2(min,p);
    }

    /**
     * 更相减损术+移位(最优)
     * @param a
     * @param b
     * @return
     */
    public static int getGreatestCommonDivisor3(int a, int b){
        if(a == b){
            return a;
        }

        if ((a&1)==0 && (b&1)==0){
            return getGreatestCommonDivisor3(a>>1,b>>1)<<1;
        }
        if((a&1)==0 && (b&1)!=0){
            return getGreatestCommonDivisor3(a>>1,b);
        }
        if((a&1)!=0 && (b&1)==0){
            return getGreatestCommonDivisor3(a,b>>1);
        }
        if((a&1)!=0 && (b&1)!=0){
            int min = a > b ? b : a;
            int max = a > b ? a : b;
            return getGreatestCommonDivisor3(min,max-min);
        }


        return 0;
    }

    public static void main (String[] args){
        System.out.println("(1) The Greatest Common Divisor is: " + getGreatestCommonDivisor(24,8));
        System.out.println("(2) The Greatest Common Divisor is: " + getGreatestCommonDivisor2(24,8));
        System.out.println("(3) The Greatest Common Divisor is: " + getGreatestCommonDivisor3(24,8));

    }

}

 结果:

(1) The Greatest Common Divisor is: 8
(2) The Greatest Common Divisor is: 8
(3) The Greatest Common Divisor is: 8


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM