java 算法基础之一寻找最大公约数
2012-09-03 09:26
369 查看
最近发现在搞Android的都要懂一点数据结构和算法才能进阶到高手,所以就回去复习了一下基础,为一些公司招聘做题做准备。
今天研究了一下最大公约数的求法,在网上也找了不同的解法,现在就想总结一下,拿出来分享给大家,共同 学习
首先讲一个什么是公约数,这个问题我们小学都学过,可能有一部分人已经忘记了,所以还是讲一下,假设有两个数a,b,所谓的公约数就是能把a,b整除的最大整数。
明白了要求我们就来解决问题,一拿到问题我们都应该都能想到一个方法,就是使用穷举法,从2开始一个个找,到一个两个都能除的就记录起来,一直找到小于min(a,b)结束,
记录到的值就是他们的最大公约数代码由下:
?
代码片段,双击复制
第二种方法是使用欧几里德算法,这个已经有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;
所以得证;
代码实现由下:
?
代码片段,双击复制
第三种方法是上一种的变形
我们在对大整数求最大公约数,第二种方法的效率就出现了瓶颈,实际上对于大整数而言,取模运算(用到除法)的开销非常的昂贵,这就是欧几里得算法的局限性,那么我们就得优化一下它了,借鉴欧几里得的辗转相除法,既然是取模运算导致的问题,那么我们就不用取模运算,换用“-”运算,即 f(x,y)=f(x-y,y);深入考虑一下发现在算法运行的过程可能会出现x<y的情况,这时候要交换x和y,但是结果不受影响。
这个方法的证明可以看上面一种给出的证明,细想一下都是一样的
实现代码也很简单:
?
代码片段,双击复制
在算法的效率上第二种和第三种都有个自的局限性,一个在大整数上,一个在迭代上, 我们还可以找到一个综合上面两种的算法就是,一步步的简化a,b这两个数,简化的方法由下:
[align=left](1)如果y=k*y1,x=k*x1.那么有f(x,y)=k*f(x1,y1)[/align]
[align=left](2)如果x=p*x2,p为素数,并且y%p != 0,那么f(x,y) = f(p*x2,y) = f(x2,y)[/align]
[align=left]于是我们得到下面的解决方法:[/align]
[align=left]将p = 2,[/align]
[align=left]若x,y均为偶数,f(x,y) = 2*f(x/2,y/2) = 2*f(x>>1,y>>1);[/align]
[align=left]若x是偶数,y是奇数,f(x,y) = f(x/2,y) = f(x>>1,y);[/align]
[align=left]若x是奇数,y是欧式,f(x,y) = f(x,y/2) = f(x,y>>1);[/align]
[align=left]若x和y均为奇数,f(x,y) = f(y,x-y)。这时x-y一定是偶数,下一步一定会除以2。[/align]
上面的方法来源都可以用到上面的证明过程,
代码实现由下:
?
代码片段,双击复制
上面的代码都比较简单,我就没有做注解了,这些思想大部分都来自了网络,代码自己重写过,有不对之处还请大家指出,共同学习。
全部代码:
今天研究了一下最大公约数的求法,在网上也找了不同的解法,现在就想总结一下,拿出来分享给大家,共同 学习
首先讲一个什么是公约数,这个问题我们小学都学过,可能有一部分人已经忘记了,所以还是讲一下,假设有两个数a,b,所谓的公约数就是能把a,b整除的最大整数。
明白了要求我们就来解决问题,一拿到问题我们都应该都能想到一个方法,就是使用穷举法,从2开始一个个找,到一个两个都能除的就记录起来,一直找到小于min(a,b)结束,
记录到的值就是他们的最大公约数代码由下:
?
欧几里德就给了我们一个很好的定理,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;
所以得证;
代码实现由下:
?
我们在对大整数求最大公约数,第二种方法的效率就出现了瓶颈,实际上对于大整数而言,取模运算(用到除法)的开销非常的昂贵,这就是欧几里得算法的局限性,那么我们就得优化一下它了,借鉴欧几里得的辗转相除法,既然是取模运算导致的问题,那么我们就不用取模运算,换用“-”运算,即 f(x,y)=f(x-y,y);深入考虑一下发现在算法运行的过程可能会出现x<y的情况,这时候要交换x和y,但是结果不受影响。
这个方法的证明可以看上面一种给出的证明,细想一下都是一样的
实现代码也很简单:
?
[align=left](1)如果y=k*y1,x=k*x1.那么有f(x,y)=k*f(x1,y1)[/align]
[align=left](2)如果x=p*x2,p为素数,并且y%p != 0,那么f(x,y) = f(p*x2,y) = f(x2,y)[/align]
[align=left]于是我们得到下面的解决方法:[/align]
[align=left]将p = 2,[/align]
[align=left]若x,y均为偶数,f(x,y) = 2*f(x/2,y/2) = 2*f(x>>1,y>>1);[/align]
[align=left]若x是偶数,y是奇数,f(x,y) = f(x/2,y) = f(x>>1,y);[/align]
[align=left]若x是奇数,y是欧式,f(x,y) = f(x,y/2) = f(x,y>>1);[/align]
[align=left]若x和y均为奇数,f(x,y) = f(y,x-y)。这时x-y一定是偶数,下一步一定会除以2。[/align]
上面的方法来源都可以用到上面的证明过程,
代码实现由下:
?
全部代码:
相关文章推荐
- java基础算法之通过辗转相除求 最大公约数
- 蓝桥杯 算法训练 寻找数组中最大值 JAVA
- 基础算法—求最大公约数
- Java实现算法导论中最大公约数欧几里得算法
- Java基础编程1—最大公约数和最小公倍数
- Java求解两个非负整数最大公约数算法【循环法与递归法】
- java操练之求两数最大公约数的两种算法思路
- java语言求最小公倍数和最大公约数的三种算法
- JAVA代码—算法基础:寻找丑数
- java算法之最大公约数及最小公倍数
- java小算法—输入两个正整数m和n,求其最大公约数和最小公倍数
- JAVA代码—算法基础:寻找缺失的数组元素
- 算法-蓝桥杯-算法训练 寻找数组中最大值 (JAVA)
- java实现最大公约数和最小公倍数(每天一道算法题)
- 蓝桥杯 - 算法训练 - 寻找数组中最大值 - Java
- Euclid算法求最大公约数--java实现
- JAVA代码—算法基础:寻找完美的数(算法优化详解)
- JAVA代码—算法基础:子数组的最大累加和问题
- 算法基础-最大公约数
- 三种算法求最大公约数——Java实现