相关介绍:

 最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。a,b的最大公约数记为gcd(a,b)。同样的,a,b,c的最大公约数记为gcd(a,b,c),多个整数的最大公约数也有同样的记号。求最大公约数有多种方法,这里介绍两种常见的算法,分别为辗转相除法和更相减损术。

辗转相除法:

 辗转相除法,又名欧几里得算法(Euclidean algorithm),目的是求出两个正整数的最大公约数。它是已知最古老的算法, 其可追溯至公元前300年前。

 这条算法基于一个定理:两个正整数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的最大公约数;再然后计算出c除以d的余数e,把问题转化成求出d和e的最大公约数……

以此类推,逐渐把两个较大整数之间的运算简化成两个较小整数之间的运算,直到两个数可以整除,或者其中一个数减小到1为止。

示例代码:

public int getGreatestCommonDivisor(int numberA,int numberB)
{
int result=1;
if(numberA>numberB)
result=gcd(numberA,numberB);
else
result=gcd(numberB,numberA)
return result;
}
//用于递归的求解最大公约数
private int gcd(int a,int b)
{
if(a%b==0)
return b;
else
return gcd(b,a%b);
}

对于辗转相除法,当两个整数的值较大时,做a%b运算的性能会较低。但是当两个数的值相差较大时,其运行的计算的次数较少。

更相减损术:

 更相减损术,出自于中国古代的《九章算术》,也是一种求最大公约数的算法。

 他的原理更加简单:两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。比如10和25,25减去10的差是15,那么10和25的最大公约数,等同于10和15的最大公约数。

 由此,我们同样可以通过递归来简化问题。首先,我们先计算出a和b的差值c(假设a>b),把问题转化成求出b和c的最大公约数;然后计算出c和b的差值d(假设c>b),把问题转化成求出b和d的最大公约数;再然后计算出b和d的差值e(假设b>d),把问题转化成求出d和e的最大公约数……

以此类推,逐渐把两个较大整数之间的运算简化成两个较小整数之间的运算,直到两个数可以相等为止,最大公约数就是最终相等的两个数。

示例代码:

public int gcd(int numberA,int numberB)
{
if(numberA==numberB)
return numberA;
if(numberA>numberB)
return gcd(numberA-numberB,numberB);
else
return gcd(numberBa-numberA,numberA);
}

对于更相减损术,其依靠的是两数求差的方式来递归的,当其两个数相差悬殊的时候,递归调用进行计算的次数较多。

为此,考虑将辗转相除法和更相减损术这两个方法结合起来使用,可以达到更优的性能。我们可以发现,对于给定的正整数a和b,不难得到如下的结论。其中gcb(a,b)的意思是a,b的最大公约数函数:

  1. 当a和b均为偶数,gcb(a,b) = 2*gcb(a/2, b/2) = 2*gcb(a>>1, b>>1)

  2. 当a为偶数,b为奇数,gcb(a,b) = gcb(a/2, b) = gcb(a>>1, b)

  3. 当a为奇数,b为偶数,gcb(a,b) = gcb(a, b/2) = gcb(a, b>>1)

  4. 当a和b均为奇数,利用更相减损术运算一次,gcb(a,b) = gcb(b, a-b), 此时a-b必然是偶数,又可以继续进行移位运算。

比如计算10和25的最大公约数的步骤如下:

  1. 整数10通过移位,可以转换成求5和25的最大公约数

  2. 利用更相减损法,计算出25-5=20,转换成求5和20的最大公约数

  3. 整数20通过移位,可以转换成求5和10的最大公约数

  4. 整数10通过移位,可以转换成求5和5的最大公约数

  5. 利用更相减损法,因为两数相等,所以最大公约数是5

在两数比较小的时候,暂时看不出计算次数的优势,当两数越大,计算次数的节省就越明显。

示例代码如下:

public int gcd(int numberA,int numberB)
{
if(numberA==numberB)
return nmberA;
//保证参数A用于大于等于参数B,为减少代码量
if(numberA<numberB)
return gcd(numberB,numberA);
else
{
//和1做按位与运算,判断奇偶 if(numberA&1==0 && numberB&1==0)
return gcd(numberA>>1,numberB>>1);
else if(numberA&1==0 && numberB&1==1)
return gcd(numberA>>1,numberB);
else if(numberA&1==1&&numberB&1==0)
return gcd(numberA,bumberB>>1);
else
return gcd(numberA,numberA-numberB);
}
}

最后总结一下上述所有解法的时间复杂度:

  1. 辗转相除法:时间复杂度不太好计算,可以近似为O(log(min(a, b))),但是取模运算性能较差。

  2. 更相减损术:避免了取模运算,但是算法性能不稳定,最坏时间复杂度为O(max(a, b)))

  3. 更相减损术与移位结合:不但避免了取模运算,而且算法性能稳定,时间复杂度为O(log(max(a, b)))

回到目录|·(工)·)

博文参考自:漫画算法:辗转相除法是什么鬼?

K:求取两个数的最大公约数的两个算法的更多相关文章

  1. Gym 101064 D Black Hills golden jewels 【二分套二分/给定一个序列,从序列中任意取两个数形成一个和,两个数不可相同,要求求出第k小的组合】

    D. Black Hills golden jewels time limit per test 2 seconds memory limit per test 256 megabytes input ...

  2. python 函数求两个数的最大公约数和最小公倍数

    1. 求最小公倍数的算法: 最小公倍数  =  两个整数的乘积 /  最大公约数 所以我们首先要求出两个整数的最大公约数, 求两个数的最大公约数思路如下: 2. 求最大公约数算法: 1. 整数A对整数 ...

  3. C++中用辗转相除法求两个数的最大公约数和最小公倍数

    两个数的最大公约数:不能大于两个数中的最小值,算法口诀:小的给大的,余数给小的,整除返回小的,即最大公约数,(res=max%min)==0?  max=min,min=res return min; ...

  4. c语言实践:求两个数的最大公约数

    我的思路是这样的:比如12和16这两个数.先理解一下概念,什么叫最大公约数.就是12有很多个因数,16也有很多个因数,这两堆因数中有一些重合的因数,在这些重合的因数中找到那个最大的.那么最大公约数一定 ...

  5. 求两个数的最大公约数&求N个数的最大公约数

    一.求两个数的最大公约数 如何编程计算N个数的最大公约数(Greatest common divisor)呢?第一想法那便是两两计算,但是往往最简单的想法是不怎么靠谱的.下面用递归来解决.递归有一大好 ...

  6. Java数据结构与算法之---求两个数的最大公约数(欧几里得算法)

    一个简单的小算法来获取两个数的最大公约数, public class Test { public static void main(String[] args) { long result = gcd ...

  7. hdu 4630 查询[L,R]区间内任意两个数的最大公约数

    No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. C实现辗转相除法求两个数的最大公约数

    什么是辗转相除法? 辗转相除法(又名欧几里德算法),它主要用于求两个正整数的最大公约数.是已知的最古老的算法. 用辗转相除法求132和72的最大公约数的步骤: 132 / 72 = 1 ... 60 ...

  9. 求两个数的最大公约数(Euclid算法)

    求两个数 p 和 q 的最大公约数(greatest common divisor,gcd),利用性质 如果 p > q, p 和 q 的最大公约数 = q 和 (p % q)的最大公约数. 证 ...

随机推荐

  1. 现在就启用 HTTPS,免费的!

    现在就启用 HTTPS,免费的! 现在,你应该能在访问https://konklone.com的时候,在地址栏里看到一个漂亮的小绿锁了,因为我把这个网站换成了HTTPS协议.一分钱没花就搞定了. 为什 ...

  2. Java 文件本地上传、下载和预览的实现

    以下方法为通用版本 实测图片和pdf 都没有问题 上传方法需要前端配合post请求 ,下载前端用a标签就可以,预览 前端使用ifrme标签   ,就可以实现基本功能... 1.文件本地上传 publi ...

  3. day3.python 学习之列表

    python中列表用[ ]表示, list =  [ ] #表示一个空列表 1.list = [ 'A','B','C',‘D’] print(list[0]) # 表示打印出列表中的第一个元素,列表 ...

  4. Could not parse UiSelector argument: 'XXX' is not a string 错误解决办法

    ebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.ANDROID_UIAUTOMATOR,new UiS ...

  5. 剑指offer——面试题29:顺时针打印矩阵

    #include"iostream" #include"stdio.h" using namespace std; void PrintMatrixInCirc ...

  6. OpenERP 中的on_change方法总结

    1.xml中应为on_change=""的形式 2.py文件中 self,cr,uid,ids为必备参数,后面的参数根据xml文件中的参数的数量而定 3.return的是一个字典, ...

  7. sql server 2008 R2 配置管理工具打不开

    使用 sql server 配置管理工具是报如下错误: 解决方法:   1 找出 sqlmgmproviderxpsp2up.mof 这个文件的位置   2 以管理员身份运行 mofcomp &quo ...

  8. Java Web入门学习(一) STS与Tomcat配置

    Java Web学习(一) STS与Tomcat配置 一.IDE的选择 使用基于Eclipse的STS Ide ,个人感觉挺好用的. 地址:http://spring.io/tools/sts 根据以 ...

  9. WCF系列教程之WCF服务协定

    本文参考自:http://www.cnblogs.com/wangweimutou/p/4422883.html,纯属读书笔记,加深记忆 一.服务协定简介: 1.WCF所有的服务协定层里面的服务接口, ...

  10. ifram的使用 左边是<a>链接 右边是对应网页嵌套的显示网页链接内容 和toggle的收放用法

    1.ifram的使用 左边是<a>链接  右边是对应网页嵌套的显示网页链接内容 <div class="container"> <div class= ...