`

java 算法基础之一寻找最大公约数

 
阅读更多
最近发现在搞Android的都要懂一点数据结构和算法才能进阶到高手,所以就回去复习了一下基础,为一些公司招聘做题做准备。
今天研究了一下最大公约数的求法,在网上也找了不同的解法,现在就想总结一下,拿出来分享给大家,共同 学习
首先讲一个什么是公约数,这个问题我们小学都学过,可能有一部分人已经忘记了,所以还是讲一下,假设有两个数a,b,所谓的公约数就是能把a,b整除的最大整数。

明白了要求我们就来解决问题,一拿到问题我们都应该都能想到一个方法,就是使用穷举法,从2开始一个个找,到一个两个都能除的就记录起来,一直找到小于min(a,b)结束,
记录到的值就是他们的最大公约数代码由下:
//找出最大公约数,穷举法
        public static int getMaxDivide_ab(int a,int b){
                int value=1;
                int max;
                int min;
                if(a==b){
                        return a;
                }
                if(a>b){
                        max=a;
                        min=b;
                }else{
                        max=b;
                        min=a;
                }
                for(int i=2;i<min;i++){
                        if(0==max%i && 0==min%i){
                                value=i;
                        }
                }
                return value;
        }



第二种方法是使用欧几里德算法,这个已经有2000+年的历史了,这个比起上一个来的要高效,假设我们的最大公约数表示为f(a,b),并且有a>=b>0,
欧几里德就给了我们一个很好的定理,f(a,b)=f(b,a%b),有了这个等式我们就很容易得出这个算法的递归式,现在我们来看下这个等式是怎么来的
设有 r=a/b ,q=a%b 
所以就有 a=a/b*b+q  ----(这里的a/b*b!=a   ,原因就是我们用的是整数来计算的)
也就是a=r*b+q     变换一下有:q=a-r*b      设d=f(a,b),a/d=m,b/d=n;则  有q=dm-r*dn=d(m-rn)
所以q/d也为0;设d|q表示d是q的约数;以下相同;
又有d|b;所以有d|(b,q),设D是(b,q)的最大公约数,则会有d<=D=f(b,q);

再回到前面r=a/b,q=a%b这两个条件有
a=r*b+q,由于D|(b,q),所以D|a,所以有D|(a,b)
所以有D<=d=f(a,b),结合上部分就有d<=D <+d,及D=d;
所以得证;
代码实现由下:
public static int oujilide(int a,int b){
                if(a<b){
                        int temp;
                        temp=a;
                        a=b;
                        b=temp;
                }
                if(0==b){
                        return a;
                }
                return oujilide(b,a%b);
        }

第三种方法是上一种的变形

我们在对大整数求最大公约数,第二种方法的效率就出现了瓶颈,实际上对于大整数而言,取模运算(用到除法)的开销非常的昂贵,这就是欧几里得算法的局限性,那么我们就得优化一下它了,借鉴欧几里得的辗转相除法,既然是取模运算导致的问题,那么我们就不用取模运算,换用“-”运算,即 f(x,y)=f(x-y,y);深入考虑一下发现在算法运行的过程可能会出现x<y的情况,这时候要交换x和y,但是结果不受影响。
这个方法的证明可以看上面一种给出的证明,细想一下都是一样的
实现代码也很简单:
public static int xymod(int a,int b){
                if(a<b){
                        int temp;
                        temp=a;
                        a=b;
                        b=temp;
                }
                if(0==b){
                        return a;
                }
                return xymod(a-b,b);
        }

在算法的效率上第二种和第三种都有个自的局限性,一个在大整数上,一个在迭代上, 我们还可以找到一个综合上面两种的算法就是,一步步的简化a,b这两个数,简化的方法由下:

(1)如果y=k*y1,x=k*x1.那么有f(x,y)=k*f(x1,y1)
(2)如果x=p*x2,p为素数,并且y%p != 0,那么f(x,y) = f(p*x2,y) = f(x2,y)
于是我们得到下面的解决方法:
将p = 2,
若x,y均为偶数,f(x,y) = 2*f(x/2,y/2) = 2*f(x>>1,y>>1);
若x是偶数,y是奇数,f(x,y) = f(x/2,y) = f(x>>1,y);
若x是奇数,y是欧式,f(x,y) = f(x,y/2) = f(x,y>>1);
若x和y均为奇数,f(x,y) = f(y,x-y)。这时x-y一定是偶数,下一步一定会除以2。
上面的方法来源都可以用到上面的证明过程,
代码实现由下:
public static int moveCombe(int a,int b){
                if(a<b){
                        return moveCombe(b, a);
                }
                if(0==b){
                        return a;
                }
                if(isTwo(a)){
                        if(isTwo(b)){
                                return moveCombe(a/2, b/2)*2;
                        }
                        return moveCombe(a/2, b);
                }else{
                        if(isTwo(b)){
                                return moveCombe(a, b/2);
                        }
                        return moveCombe(b, a-b);
                }
                        
                        
        }
        private static boolean isTwo(int a) {
                if(0==a%2){
                        return true;
                }else{
                        return false;
                }
        }

上面的代码都比较简单,我就没有做注解了,这些思想大部分都来自了网络,代码自己重写过,有不对之处还请大家指出,共同学习。
分享到:
评论

相关推荐

    JAVA编写两个数的最大公约数

    在IT领域,尤其是在编程技术中,寻找两个或多个数的最大公约数(Greatest Common Divisor,简称GCD)是一项基础而重要的技能。本篇文章将基于提供的文件信息,深入解析如何使用Java语言来实现这一功能,并进一步拓展...

    n个整数的最大公约数,n由键盘输入

    在编程领域,最大公约数(Greatest Common Divisor, GCD)是一个常见的数学概念,用于找出两个或多个整数的最大公共除数。本问题聚焦于寻找n个整数的最大公约数,其中n是从键盘输入的。这样的程序设计有助于理解递归...

    java求最大公约数与最小公倍数的方法示例

    下面是一个简单的Java程序,演示如何计算最大公约数和最小公倍数: ```java public class Gongyueshu { public static void main(String[] args) { int m = Integer.parseInt(args[0]); int n = Integer.parseInt...

    JAVA算法题目集合.pdf

    1. **最大公约数与最小公倍数**:求两个数的最大公约数(GCD)和最小公倍数(LCM)。常见的方法是欧几里得算法(辗转相除法)求GCD,然后用GCD求LCM。 2. **百鸡百脚问题**:典型的背包问题,可以通过穷举法解决,...

    JAVA算法题目集合程序习题:

    可以通过欧几里得算法求最大公约数,然后用两数乘积除以最大公约数得到最小公倍数。 - A2. **百鸡百脚问题**:经典的数学问题,通过线性方程组求解。例如,设母鸡、公鸡、小鸡分别为x、y、z,列出方程求解。 - A3....

    2_最大公约数_

    标题中的“2_最大公约数_”可能是指一个关于计算最大公约数(Greatest Common Divisor, GCD)的编程任务或教程的一部分。这个标题暗示我们将讨论如何在计算机程序中找到两个或多个整数的最大公约数。最大公约数是...

    java算法练习试题

    【程序 6】求两个正整数的最大公约数(GCD)和最小公倍数(LCM)通常使用欧几里得算法(辗转相除法)。对于GCD,用较大的数除以较小的数,然后用余数替换较大的数,重复这个过程,直到余数为0,最后的除数就是GCD。...

    用递归算法求最大公因子2

    在这种情况下,我们将讨论如何使用递归算法来寻找两个整数的最大公因数,并结合JUnit进行单元测试以确保算法的正确性。 首先,我们定义一个递归函数`gcd(a, b)`,其中`a`和`b`是我们要找最大公因数的两个整数。递归...

    java经典算法例子

    下面我们将深入探讨几个与Java相关的算法例子,包括求最大公约数、垃圾回收机制、单例模式的实现、寻找数组中重复的数字以及Servlet的生命周期。 1. **求两个数的最大公约数**: 使用欧几里得原理(辗转相除法)来...

    Java 算法源码集合

    Java算法源码集合是一个汇集了各种经典算法实现的资源库,旨在帮助开发者加深对算法的理解,提高编程技能。源码中的实现可能来自网络上的不同来源,因此可能存在一些错误或不完善之处,但在学习和实践中,我们可以...

    java_algorithm_Daquann.rar_java算法

    Java算法大全涵盖了编程中最核心的部分,它涉及到计算机科学的基础理论以及实际编程中的高效问题解决技巧。这个名为"java_algorithm_Daquann.rar"的压缩包很可能包含了一系列Java实现的经典算法,帮助学习者深入理解...

    java最新算法大全v1.0

    8. **数论问题**:学习数论基础,如质数检测、最大公约数和最小公倍数计算、模运算等,这些都是密码学和计算机安全的基础。 9. **经典算法**:研究一些经典的算法问题,如八皇后问题、汉诺塔、约瑟夫环等,通过这些...

    JAVA算法题目集合.docx

    取两个数的最小公倍数/最大公倍数:可以使用辗转相除法(欧几里得算法)求最大公约数(GCD),然后用两数乘积除以GCD得到最小公倍数(LCM)。 A2. 百鸡百脚问题:这是一个经典的数学问题,可以通过设立方程求解。...

    java算法题目.pdf

    6. **最大公约数与最小公倍数**(程序6):最大公约数(GCD)和最小公倍数(LCM)可以用辗转相除法(欧几里得算法)求解,GCD(a, b) = GCD(b, a mod b),当b为0时,a就是GCD;LCM可以通过GCD计算,LCM(a, b) = a * b...

    java经典算法40题

    最大公约数是两个或多个整数共有的约数中最大的一个;最小公倍数是能够同时整除这两个数的最小正整数。可以使用欧几里得算法(Euclidean Algorithm)来计算GCD,而LCM可以通过GCD来计算,公式为`LCM(a, b) = |a * b|...

    java代码-* 最大公约数

    以下是一个使用欧几里得算法实现最大公约数的Java代码示例: ```java public class GCD { public static int gcd(int num1, int num2) { if (num2 == 0) { return num1; } else { return gcd(num2, num1 % num...

    java基础编程题

    - 使用辗转相除法(欧几里得算法)求最大公约数,通过不断用较大的数除以较小的数直到余数为零,最后的除数就是最大公约数。最小公倍数可以通过两数乘积除以最大公约数得到。 7. **StChar.java** - 统计字符类型 ...

    java算法题目[参考].pdf

    Java算法题目涵盖了许多基础到进阶的编程概念,主要涉及数据结构、算法分析以及逻辑推理。以下是基于这些题目所涵盖的知识点的详细说明: 1. **斐波那契数列**(程序1):这是一种经典的数学序列,每项是前两项的和...

Global site tag (gtag.js) - Google Analytics