求两数最大公约数的算法
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);
}
参考文章:
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号