Greatest Common Divisor
在数论和程序实现中都经常用到,很重要,也有很多方法
1. 穷举法
输入a, b(假设a>b)
依次测试b、b-1…,直到可同时被a和b整除
2. 更相减损法(九章算术)
该方法特点是只用减法,单次计算代价小,但迭代次数较多
int gcd(int& a, int& b)
{
while(a>0 && b>0)
{
if(a < b)
swap(a, b);
int tmp = a-b;
a = b;
b = tmp;
}
return a>0?a:b;
}
3. 辗转相除法(欧几里得法)
该方法特点是迭代较快;但是单次计算取余,代价大
int gcd(int& a, int& b )
{
if(a<b)
swap(a, b);
while(b)
{
int tmp = a%b;
a = b;
b = tmp;
}
return a;
}
4. Stein算法(奇偶法)
此种方法是将解法2和解法3结合起来,降低计算复杂度的同时也降低迭代次数。
i) 若 a, b均为偶数,
f(a, b)=2∗f(a/2, b/2)=2∗f(a>>1, b>>1)
ii) 若a为偶,而b为奇
f(a, b)=f(a/2, b)=f(a>>1, b)
iii) 若a为奇,b为偶
f(a, b)=f(a, b/2)=f(a, b>>1)
iv) 若a, b均为奇
f(a,b)=f(b,a−b)
在f(a, b) = f(a, a - b)之后,(a - b)是一个偶数,下一步一定会有除以2的操作。
因此最坏情况下时间复杂度为 O(log2(max(a,b)))