最大公约数和最小公倍数
没错,今天要记录的就是这位老得不能再老的老朋友,也就是所谓的gcd算法,我还记得当时机器人面试的时候学长问了一句会不会写gcd,我心想这是啥玩意,得知是求最大公约数之后嗤之以鼻,说肯定可以。然而。。。。。。一年半之后我再次刷到的时候,脑子里全部都是什么辗转相除法,怎么实现的脑子里一团浆糊,只记得要设置一个中间变量来存储中间求得的余数,不由得觉得自己更加的失败。索性就直接记录下来,把这个老朋友给彻底征服。
首先我们先从最小公倍数开始,最小公倍数的求法很单一,就是两数相乘再除以最大公约数,所以这实际上是一个问题,求出最大公约数,最小公倍数就自然而然出来了。最大公约数主要有三种求法(可能更多,不过先掌握这三种),分别是辗转相除法、相减法和穷举法。最符合我们思维的方法就是穷举法,设立一个临时变量i,让它从1开始递增小于两个数中较小的那个数,然后判断是否可以同时被两个数整除,可以就将其赋值给中间变量,最后循环结束,留下的就是最大的公约数。不过这种方法比较蠢,速度在两个数很大的情况下会比较慢。
穷举法:
int gcd_enu(int m, int n){
int temp = 0, result = 0;
if(m > n){temp = m; m = n; n = temp;}
for(int i = 1; i <= m; i++){
if(m % i == 0 && n % i == 0){
result = i;
}
}
return result;
}
然后就是两种我当时怎么都理解不了的方法,辗转相除法和更相减损法,前者是欧几里得发现的方法,后者是记录在《九章算术》里的方法。可谓是中西两方殊途同归,这两种方法难理解的原因就是因为它们都建立在一个基本原理的基础上进行求解:对于整数A、B、C,如果A-B=C,那么A与B之间的最大公约数,也是A、B、C三者之间的最大公约数。
基本原理所以一个通过相减,一个通过除余,将目标数据给减小,最终减到其本身就是最大公约数。(可以简单地这么理解)
更相减损法:
int gcd_sub(int m, int n){
while(m != n){
if(m > n){
m -= n;
}
else{
n -= m;
}
}
return m;
}
辗转相除法:
int gcd_div(int m, int n){
int temp = 0;
while(n != 0){//余数为0时
temp = m % n;
m = n;
n = temp;
}
return m;
}
明显可以看出的是,辗转相除法各个方面都很优秀,所以只记住这一个算法也可以。
网友评论