求一个数的最大公约数的三种思路——解题笔记
编程之美上的题目:求一个数的最大公约数。
这道题目有三种解题思路,总结如下:
直接使用辗转相除法,这个不多介绍,代码如下:
// 直接辗转相除法 int gcd1(int a, int b) { for(int m = a%b; m != 0; m = a%b) { a = b; b = m; } return b; }
改进辗转相除法中取余(除法)运算,改为减法。这里可以利用一个规律,x和y的最大公约数等于x-y和y的最大公约数。不过需要判断x和y的大小。
代码如下:
// x和y的最大公约数等于x-y和y的最大公约数 int gcd2(int a, int b) { if(a < b) swap(a, b); // 默认前面的数较大 while(b) return gcd2(b, a-b); // 递归 return a; }
分析:虽然这种方法只有减运算,用的是递归的实现形式。但是,需要递归的次数比较多,假如a和b之间相差较大,那么每次都只是相减,会迭代很多次。
可以结合前面两个思路的优点,我们不全都是用减运算,偶尔用一次除法,不过只是除以2,即判断奇偶数,而且用移位运算实现。
代码如下:
// 通过判断奇偶数,减少迭代次数 bool isEven(int a) { return (a & 1); // 按位与来判断奇偶数 } int gcd3(int a, int b) { if(a < b) swap(a, b); // 默认前面的数较大 if(!b) return a; if(isEven(a)) // if a is even { if(isEven(b)) // b is even at the same time return (gcd3(a>>1, b>>1) <<1); // note that *2 else return (gcd3(a>>1, b)); // if only a is even } else { if(isEven(b)) return gcd3(a, b>>1); // is only b is even else return gcd3(a-b, b); // neither a or nor b is even } }
原文地址:http://blog.csdn.net/puqutogether/article/details/43446205