K:求取两个数的最大公约数的两个算法
相关介绍:
最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。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的最大公约数函数:
当a和b均为偶数,gcb(a,b) = 2*gcb(a/2, b/2) = 2*gcb(a>>1, b>>1)
当a为偶数,b为奇数,gcb(a,b) = gcb(a/2, b) = gcb(a>>1, b)
当a为奇数,b为偶数,gcb(a,b) = gcb(a, b/2) = gcb(a, b>>1)
当a和b均为奇数,利用更相减损术运算一次,gcb(a,b) = gcb(b, a-b), 此时a-b必然是偶数,又可以继续进行移位运算。
比如计算10和25的最大公约数的步骤如下:
整数10通过移位,可以转换成求5和25的最大公约数
利用更相减损法,计算出25-5=20,转换成求5和20的最大公约数
整数20通过移位,可以转换成求5和10的最大公约数
整数10通过移位,可以转换成求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);
}
}
最后总结一下上述所有解法的时间复杂度:
辗转相除法:时间复杂度不太好计算,可以近似为O(log(min(a, b))),但是取模运算性能较差。
更相减损术:避免了取模运算,但是算法性能不稳定,最坏时间复杂度为O(max(a, b)))
更相减损术与移位结合:不但避免了取模运算,而且算法性能稳定,时间复杂度为O(log(max(a, b)))
博文参考自:漫画算法:辗转相除法是什么鬼?
K:求取两个数的最大公约数的两个算法的更多相关文章
- 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 ...
- python 函数求两个数的最大公约数和最小公倍数
1. 求最小公倍数的算法: 最小公倍数 = 两个整数的乘积 / 最大公约数 所以我们首先要求出两个整数的最大公约数, 求两个数的最大公约数思路如下: 2. 求最大公约数算法: 1. 整数A对整数 ...
- C++中用辗转相除法求两个数的最大公约数和最小公倍数
两个数的最大公约数:不能大于两个数中的最小值,算法口诀:小的给大的,余数给小的,整除返回小的,即最大公约数,(res=max%min)==0? max=min,min=res return min; ...
- c语言实践:求两个数的最大公约数
我的思路是这样的:比如12和16这两个数.先理解一下概念,什么叫最大公约数.就是12有很多个因数,16也有很多个因数,这两堆因数中有一些重合的因数,在这些重合的因数中找到那个最大的.那么最大公约数一定 ...
- 求两个数的最大公约数&求N个数的最大公约数
一.求两个数的最大公约数 如何编程计算N个数的最大公约数(Greatest common divisor)呢?第一想法那便是两两计算,但是往往最简单的想法是不怎么靠谱的.下面用递归来解决.递归有一大好 ...
- Java数据结构与算法之---求两个数的最大公约数(欧几里得算法)
一个简单的小算法来获取两个数的最大公约数, public class Test { public static void main(String[] args) { long result = gcd ...
- hdu 4630 查询[L,R]区间内任意两个数的最大公约数
No Pain No Game Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- C实现辗转相除法求两个数的最大公约数
什么是辗转相除法? 辗转相除法(又名欧几里德算法),它主要用于求两个正整数的最大公约数.是已知的最古老的算法. 用辗转相除法求132和72的最大公约数的步骤: 132 / 72 = 1 ... 60 ...
- 求两个数的最大公约数(Euclid算法)
求两个数 p 和 q 的最大公约数(greatest common divisor,gcd),利用性质 如果 p > q, p 和 q 的最大公约数 = q 和 (p % q)的最大公约数. 证 ...
随机推荐
- ArrayList 和 Vector 的区别
这两个类都实现了 List 接口( List 接口继承了 Collection 接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后可以按位置索引号取 ...
- 多线程:GCD
多线程是程序开发中非常基础的一个概念,大家在开发过程中应该或多或少用过相关的东西.同时这恰恰又是一个比较棘手的概念,一切跟多线程挂钩的东西都会变得复杂.如果使用过程中对多线程不够熟悉,很可能会埋下一些 ...
- Cassandra2.0.8导入到eclipse运行
如果想通过eclipse来调试或者查看Cassandra的代码,将其project导入到eclipse之中不愧是个好选择.下面将讲述将2.0.8 版本导入elcipse的过程. 该篇文章主要参考的官方 ...
- git配置教程
一.配置ssh 1.检查本机是否有ssh key设置 如果没有则提示: No such file or directory 如果有则进入~/.ssh路径下(ls查看当前路径文件,rm删除所有文件) 2 ...
- [整理]Unicode 与 UTF8
目录 先上总结 ASCII utf-8 编码规则 UTF-16 其他 先上总结 Unicode 是一个符号集, 规定了所有符号的二进制编号. UTF8 是unicode的一种编码方式(存储, 传输方式 ...
- CF917D. Stranger Trees & TopCoder13369. TreeDistance(变元矩阵树定理+高斯消元)
题目链接 CF917D:https://codeforces.com/problemset/problem/917/D TopCoder13369:https://community.topcoder ...
- Sql语句里的递归查询 SqlServer2005和Oracle 两个版本
以前使用Oracle,觉得它的递归查询很好用,就研究了一下SqlServer,发现它也支持在Sql里递归查询举例说明:SqlServer2005版本的Sql如下:比如一个表,有id和pId字段,id是 ...
- 各种height/width总结
CSS盒模型是比较复杂的,尤其是当页面中有滚动条时,仅仅通过css来操作高度宽度是不够的,幸运的是Javascript提供了不少这样的接口.Javascript中clientHeight / clie ...
- Git学习系列之Git基本操作推送项目(图文详解)
前面博客 Git学习系列之Git基本操作提交项目(图文详解) 如果完成到一定程度,那么可以推送到远端在线仓库. 推送之前,请确保你已经设置了全局的 user.name 和 user.email, 如果 ...
- Js 中的false,零值,null,undefined和空字符串对象
转自 http://www.imkevinyang.com/2009/07/javascript-中的false零值nullundefined和空字符串对象.html 在Javascript中,我们 ...