求两数最大公约数的算法

 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 @ 2021-05-31 17:32  Jasmine_Sokko  阅读(594)  评论(0)    收藏  举报