求两数最大公约数的算法

 1.暴力解法

与手算除法思想类似。用两数直接除10以内的质数,若无余数便取其商重复此过程同时累乘此时的除数,直至用10以内的质数均除不尽为止。

复制代码
 1 int gcd(int a, int b) {
 2         int i = 1;
 3         int less,more;
 4         if(a <= b)
 5         {
 6             less = a;
 7             more = b;
 8         }
 9         else
10         {
11             less = b;
12             more = a;
13         }
14         if(more % less == 0)
15                 return less;
16         while(true)
17         {
18             if(a%2 == 0 and b%2 == 0)
19             {
20                 i *= 2;
21                 a /= 2;
22                 b /= 2;
23             }
24             else if(a%3 == 0 and b%3 == 0)
25             {
26                 i *= 3;
27                 a /= 3;
28                 b /= 3;
29             }
30             else if(a%5 == 0 and b%5 == 0)
31             {
32                 i *= 5;
33                 a /= 5;
34                 b /= 5;
35             }
36             else if(a%7 == 0 and b%7 == 0)
37             {
38                 i *= 7;
39                 a *= 7;
40                 b *= 7;
41             }
42             else
43                 break;
44         }
45         return i;
46     }
复制代码

 

2.辗转相除法。

定理:两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。

附一个讲了辗转相除法的视频:https://www.bilibili.com/video/BV1mJ411q7xw

int gcd(int a, int b){     
     int max = a > b ? a : b;
     int min = a < b ? a : b;
     if(max % min == 0) return min;
     return gcd(max % min, min);
}

 

3.更相减损术。

定理:两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。

递归实现:

int gcd(int a, int b)
{
         int max = a > b ? a : b;
         int min = a < b ? a : b;
         if(max % min == 0) return min;
         return gcd(max - min, min);
}

 

非递归实现:

while(a != b)
{
if(a > b) a -= b; else b -= a; } return a;

 

4.辗转相除法与更相减损术结合

2的缺点在于取模运算效率低下,3的缺点在于减法运算次数增加。
 

移位运算的性能非常快。对于给定的正整数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必然是偶数,又可以继续进行移位运算。

复制代码
public int gcd (int a, int b) 
{
         if(a == b) return a;
         if((a & 1) == 0 && (b & 1) == 0){
             return gcd(a >> 1, b >> 1) << 1;
         }else if((a & 1) == 0 && (b & 1) != 0){
             return gcd(a >> 1, b);
         }else if((a & 1) != 0 && (b & 1) == 0){
             return gcd(a, b >> 1);
         }else {
             int max = a > b ? a : b;
             int min = a < b ? a : b;
             return gcd(min, max - min);
}
复制代码

 

 

参考文章:

漫画算法:辗转相除法是什么鬼?
posted @   Jasmine_Sokko  阅读(578)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示