★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/11032151.html 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

1、定义:

GCD:最大公约数(Greatest Common Divisor)。指两个或多个整数共有约数中最大的一个。

LCM:最小公倍数(Least Common Multiple)。两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。

2、最小公倍数与最大公约数的关系: 

LCM(A,B)×GCD(A,B)=A×B

其中LCM是最小公倍数,GCD是最大公约数。

1  //MARK:求最小公倍数
2  func lcm(_ a:Int,_ b:Int) -> Int
3  {
4     //求最大公约数
5     let num:Int = gcd(a,b)
6     return a * b / num
7  }

所以求最小公倍数的问题可以转化为求最大公约数。

3、公约数的性质

如果b是A和B的公约数,则有:

(1)、b也是A+B的约数,即b是A,B,A+B的公约数

(2)、b也是A-B的约数,即b是A,B,A-B的公约数

(3)、更一般地,对于任意整数x、y,b也是Ax+By的约数,即b是A,B,Ax+By的公约数

(4)、根据性质(3),r = A - kB = A mod B,所以A mod B也是A+B的约数,mod是求余运算,即b是A,B,A mod B的公约数

1 gcd(A,B)
2 = gcd(B,A)
3 = gcd(A,A+B)
4 = gcd(A,A-B)
5 = gcd(A,Ax+By)
6 = gcd(A,A mod B)

求最大公约数的几个算法:

(1)、质因数分解法

(2)、更相减损术:

缺点:当两个数a和b相差太过悬殊时,递归的次数会非常多,严重影响算法性能。

(3)、辗转相除法(欧几里得算法)

缺点:因为使用了求余运算的缘故导致其在面对大整数的时候性能不够理想。我们应尽量避免使用求余运算。

(4)、Stein算法:更相减损术 + 辗转相除法

4、质因数分解法:把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是这几个数的最大公约数。

 1 //MARK:质因数分解法。不能处理为0的情况
 2 func gcd(_ a:Int,_ b:Int) -> Int
 3 {
 4     var a = a
 5     var b = b
 6     guard a != 0 && b != 0 else
 7     {
 8         return 0
 9     }
10
11     let min:Int = a < b ? a : b
12     var accumulate:Int = 1
13
14     // 以2进行分解,如果为0则变成死循环
15     while ((a & 1) == 0 && (b & 1) == 0)
16     {
17         accumulate *= 2
18         a >>= 1
19         b >>= 1
20     }
21
22     // 以大于等于3的数进行分解
23     for i in stride(from:3,through:min,by:2)
24     {
25         while ((a % i) == 0 && (b % i) == 0)
26         {
27             accumulate *= i
28             a /= i
29             b /= i
30         }
31     }
32     // 将所有公因子的乘积作为返回值
33     return accumulate
34 }

测试:
1 print(gcd(100,1000))
2 //Print 100

4、更相减损术:出自《九章算术》,成于公元一世纪左右。其作者已不可考。一般认为它是经历代各家的增补修订,而逐渐成为现今定本的,最后成书最迟在东汉前期,现今流传的大多是在三国时期魏元帝景元四年(263年),刘徽为《九章》所作的注本。

原文:

可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。

1 如果A > B,则 gcd(A,B) = gcd(B,A-B)
2 如果A < B,则 gcd(A,B) = gcd(A,B-A)

译文:

第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。

第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。

则第一步中约掉的若干个2的积与第二步中等数的乘积就是所求的最大公约数。其中所说的“等数”,就是公约数。

如图所示:两条线段长分别可表示252和105,则其中每一小分段长代表最大公约数21。如动画所示,只要辗转地从大数中减去小数,直到其中一段的长度为0,此时剩下的一条线段的长度就是252和105的最大公因数。

更相减损术的一般写法:

 1 //MARK:更相减损术
 2 func gcd(_ a:Int,_ b:Int) -> Int
 3 {
 4     var a = a
 5     var b = b
 6     //储存第一步中约掉的若干个2
 7     var ans:Int = 1
 8     //如果ab均为偶数则用2约简
 9     while(a%2==0  &&  b%2==0)
10     {
11         a /= 2
12         b /= 2
13         ans *= 2
14     }
15     //判断两数是否相等,也可以理解为直到所得的减数和差相等为止
16     while(a != b)
17     {
18         if a > b
19         {
20             //以较大的数减较小的数
21             a -= b
22         }
23         else
24         {
25             //以较大的数减较小的数
26             b -= a
27         }
28     }
29     //求第一步中约掉的若干个2与第二步中等数的乘积,并返回
30     return a*ans
31 }

更相减损术的递归写法:
1 import Foundation
2 //MARK:更相减损术
3 func gcd(_ a:Int,_ b:Int) -> Int
4 {
5     if a == b {return a}
6     return gcd(abs(a - b), min(a, b))
7 }

更相减损术的while循环写法:

 1 //MARK:更相减损术
 2 func gcd(_ a:Int,_ b:Int) -> Int
 3 {
 4     var a = a
 5     var b = b
 6     while (true)
 7     {
 8         if a > b
 9         {
10             a -= b
11         }
12         else if a < b
13         {
14             b -= a
15         }
16         else
17         {
18             return a
19         }
20     }
21 }

测试:

1 print(gcd(100,1000))
2 //Print 100

5、辗转相除法:又称欧几里得算法。两个正整数A,B的最大公约数等于其中较小值与两数相除的余数的最大公约数。

1 gcd(A, B) = gcd(B, A mod B)
2 其中:A > B

例如,计算a = 1071和b = 462的最大公约数的过程如下:从1071中不断减去462直到小于462(可以减2次,即商q0 = 2),余数是147:

  • 1071 = 2 × 462 + 147.

然后从462中不断减去147直到小于147(可以减3次,即q1 = 3),余数是21:

  • 462 = 3 × 147 + 21.

再从147中不断减去21直到小于21(可以减7次,即q2 = 7),没有余数:

  • 147 = 7 × 21 + 0.

此时,余数是0,所以1071和462的最大公约数是21,这和用素因数分解得出的结果相同。

算法的演示动画:最初的绿色矩形的长和宽分别是a = 1071、b = 462,从中不断铺上462×462的正方形直到剩下部分面积是462×147;然后再铺上147×147的正方形直至剩下21×147的面积;最后,铺上21×21的正方形时,绿色部分就没有了。即21是1071和462的最大公约数。

辗转相除法的递归写法:

1 //MARK:辗转相除法
2 func gcd(_ a:Int,_ b:Int) -> Int
3 {
4     return b == 0 ? a : gcd(b, a % b)
5 }

辗转相除法while循环写法

 1 //MARK:辗转相除法
 2 func gcd(_ a:Int,_ b:Int) -> Int
 3 {
 4     var a = a
 5     var b = b
 6     while(b != 0)
 7     {
 8         let r:Int = a % b
 9         a = b
10         b = r
11     }
12     return a
13 }

测试:

1 print(gcd(100,1000))
2 //Print 100

6、Stein算法:Stein算法由J.Stein 1961年提出,Stein算法只进行整数的移位和加减法,没有求余运算。

算法的原理:

(1)、若a和b都是偶数,则记录下公约数2,然后都除2(即右移1位);

(2)、若其中一个数是偶数,则偶数除2,因为此时2不可能是这两个数的公约数。

(3)、若两个都是奇数,则a = |a-b|,b = min(a,b),因为若d是a和b的公约数,那么d也是|a-b|和min(a,b)的公约数。

注:判断偶数的两种方式:

(1)、num % 2 == 0

(2)、num & 1 == 0

Stein算法的递归写法:

 1 //MARK:Stein算法
 2 func gcd(_ a:Int,_ b:Int) -> Int
 3 {
 4     if a == 0 {return b}
 5     if b == 0 {return a}
 6     if (a & 1) == 0 && (b & 1) == 0
 7     {
 8         return 2 * gcd(a >> 1, b >> 1)
 9     }
10     else if (a & 1) == 0
11     {
12         return gcd(a >> 1, b)
13     }
14     else if (b & 1) == 0
15     {
16         return gcd(a, b >> 1)
17     }
18     else
19     {
20         return gcd(abs(a - b), min(a, b))
21     }
22 }

Stein算法的while循环写法:

 1 //MARK:Stein算法
 2 func gcd(_ a:Int,_ b:Int) -> Int
 3 {
 4     var a = a
 5     var b = b
 6     var acc:Int = 0
 7     while((a & 1) == 0 && (b & 1) == 0)
 8     {
 9         acc += 1
10         a >>= 1
11         b >>= 1
12     }
13     while ((a & 1) == 0) {a >>= 1}
14     while ((b & 1) == 0) {b >>= 1}
15     if a < b {swap(&a,&b)}
16     while (a != 0)
17     {
18         while ((a & 1) == 0)
19         {
20             a >>= 1
21         }
22         if a < b{swap(&a,&b)}
23         a = (a - b) >> 1
24     }
25     return b << acc
26 }
27 ​
28 func swap(_ x:inout Int,_ y:inout Int)
29 {
30     x = x ^ y
31     y = x ^ y
32     x = x ^ y
33 }

测试:

1 print(gcd(100,1000))
2 //Print 100

 

转载于:https://www.cnblogs.com/strengthen/p/11032151.html

[Swift]求最大公约数和最小公倍数【用微信查看本文链接可查看到引用图片】相关推荐

  1. c语言有参有类最小公倍数,C语言求最大公约数和最小公倍数算法

    C 语言求最大公约数和最小公倍数算法 C 语言求最大公约数和最小公倍数可以说是C 语言编程学习中一个重点和难点,它常常作为计算机专业学生参加各种考试必须要把握的内容.其算法方面除常用的辗转相除法外.还 ...

  2. python计算最大公约数和最小公倍数_python怎么求最大公约数和最小公倍数

    python怎么求最大公约数和最小公倍数 一.求最大公约数 用辗转相除法求最大公约数的算法如下: 两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数.比如10和 ...

  3. C语言求最大公约数与最小公倍数

    该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/105022773 求 ...

  4. python最大公约数和最小公倍数_python怎么求最大公约数和最小公倍数

    python怎么求最大公约数和最小公倍数 一.求最大公约数 用辗转相除法求最大公约数的算法如下: 两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数.比如10和 ...

  5. 辗转相除法(欧几里得算法)求 最大公约数与最小公倍数+推论与证明。

    首先我们规定:0不参与公约数和公倍数的讨论 先来讨论最大公约数: 最大公约数求法:两个数的所有公共质数相乘. 考虑三个问题. 为什么是公共的:公共代表这个数可以被两个数都整除 为什么是质数:合数一定能 ...

  6. python求最小公倍数_python求最大公约数和最小公倍数的简单方法

    python怎么求最大公约数和最小公倍数 一.求最大公约数 用辗转相除法求最大公约数的算法如下: 两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数.比如10和 ...

  7. java - 求最大公约数和最小公倍数

    根据提示输入两个正整数 m 和 n,求其最大公约数和最小公倍数 并进行控制台输出. 原理分析 在循环中,只要除数不等于 0,用较大数除以较小的数,将小的一个数作为下一轮循环的大数,取得的余数作为下一轮 ...

  8. php怎么求最小公倍数,PHP编程求最大公约数与最小公倍数的方法示例

    本文实例讲述了PHP编程求最大公约数与最小公倍数的方法.分享给大家供大家参考,具体如下: //求最大公约数 function max_divisor($a,$b) { $n = min($a, $b) ...

  9. 求最大公约数和最小公倍数简洁写法的注意事项

    求最大公约数和最小公倍数 最简洁的写法就是一行递归的写法 有些小细节可能需要注意,下面进行了一点总结~ 1.最大公约数 简洁的写法就是这样 int gcd(int a,int b){if(b == 0 ...

最新文章

  1. 使用python moviepy提取视频中的音频,同时对音频数据进行数据可视化分析
  2. javascript基础(幼兔、小兔成兔数量等典型例题)
  3. 【Paddle】Anaconda安装PaddlePaddle和PaddleX教程
  4. sql xml 入门
  5. oracle拼接字符串报错,Oracle 中wmsys.wm_concat拼接字符串,结果过长报错解决
  6. java 注册成功跳转,写了个注册页面填了注册信息后点注册按钮居然不跳转,为什么?...
  7. HTML5本地存储——IndexedDB
  8. windows10杀死本地进程
  9. ubantu系统之快捷键使用
  10. Java中split方法对结尾空字符串不正确处理的解决方案
  11. 电脑的复制粘贴功能用不了?
  12. iOS:iOS 的 APP 如何适应 iPhone 5s/6/6Plus 三种屏幕的尺寸?
  13. psp软件设计需求分析
  14. 有看板娘的vuepress-theme-ting清新简易主题
  15. 通达OA 办公系统(Office Anywhere)动态密码配置使用详解
  16. 大数据运维实战第一课 大话 Hadoop 生态圈
  17. Python对文件的创建和读写操作
  18. NP问题真的很难理解
  19. 看上去很美--次世代游戏平台XBOX360测评
  20. Unity常见插件汇总

热门文章

  1. 真正阅读量php,科学网—博客70万阅读量与研究网8万点击量感言 - 陈安的博文
  2. Dubbo Admin 发布 v0.1;VMware 或与微软放下恩怨展开合作
  3. 自我总结--测试面试常见问题(二)
  4. docker内运行的grafana重置登录密码
  5. STM32F429 14. TIM_(一)_基本定时器
  6. PHP 优秀资源汇集(转)
  7. 用计算机看影碟是数字化过程,2012年上海市高中学业水平考试信息科技
  8. 快速学习四步法:如何用20小时,快速学习?
  9. java mail 回复邮件_JavaMail - 退回邮件( Bounced Messages)
  10. 40Gbit/s QSFP光模块的软件实现(硕士学位论文)错误指出