相关介绍:

 最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。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. 使用HttpClient出现java.io.IOException: Attempted read from closed stream

    问题描述: 使用httpClient时候,出现java.io.IOException: Attempted read from closed stream. 原始代码: public static S ...

  2. 数据结构:广义表的实现(Java)

    广义表的简单理解在这篇博文中:https://blog.csdn.net/lishanleilixin/article/details/87364496,在此不做赘述. Java实现广义表: pack ...

  3. 高斯分布(Gaussian Distribution)的概率密度函数(probability density function)

    高斯分布(Gaussian Distribution)的概率密度函数(probability density function) 对应于numpy中: numpy.random.normal(loc= ...

  4. 【kuangbin】计算几何部分最新模板

    二维几何部分 // `计算几何模板` ; const double inf = 1e20; const double pi = acos(-1.0); ; //`Compares a double t ...

  5. 开源项目-Aiguille

        项目地址: https://github.com/wwkai555/Aiguille 这个项目主要使用Android L新特性 - 最新的widget以及一些值得推荐和使用的开源库比如butt ...

  6. 在linux上安装 sql server for linux

    在linux上安装 sql server for linux Install SQL Server on Red Hat Enterprise Linux Install SQL Server To ...

  7. WCF系列教程之WCF客户端调用服务

    1.创建WCF客户端应用程序需要执行下列步骤 (1).获取服务终结点的服务协定.绑定以及地址信息 (2).使用该信息创建WCF客户端 (3).调用操作 (4).关闭WCF客户端对象 二.操作实例 1. ...

  8. 第2章—装配Bean—自动化装配Bean

    自动化装配Bean 2.1.Spring配置可选方案 ​ 装配是依赖注入DI的本质,Spring提供了以下三种注入的装配机制: 在XMl中进行显式配置 在java中进行显式配置 隐式的Bean发现机制 ...

  9. CentOS 7 下 MySql5.7 主从配置

    演示用两台全新MySql服务器: mysql1:10.10.1.55 (主) mysql2:10.10.1.56 (从) 配置主从,步骤如下:   STEP 1:在mysql1上创建复制账号 repl ...

  10. JavaScript设计模式-17.装饰者模式(下)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...