辗转相除法是计算两个数最大公约数(Greatest conmmon divisor)的一种对数复杂度算法。
问题:有两个正整数 x , y ,求 gcd(x,y):
算法证明:
设 x > y , 且 x = r + y * c , 其中 r >= 0, c >= 0 ;
1. if r = 0 then gcd( x,y) == y 为结束条件)
2. if c = 0 then 算法没有前进
3. if r > 0 && c >0 then r = x - c * y ,
易知 : 如果d 为 x, y的公约数, 则必为r = x - c*y 的公约数 ,即 x,y 的公约数必为 y, r 的公约数;
如果e 为 r和y的公约数, 有 r / e = x / e - c * y / e, r / e , c*y/e 为正整数, x / e 也为正整数,即y, r的公约数必为x,y的公约数;
综上,x,y的最大公约数等价于y, r的最大公约数由此易得递归算法:
int gcd ( int x, int y )
{
if( x < y )
swap( x, y );
int r = x % y;
if( r == 0 )
return y;
else
return gcd( y , r );
}
int main()
{
cout<< gcd( 9, 15 );
}
算法复杂度:设 x > y , 且 x = r + y * c , 其中 r = x % y , c > 0 ;
得:x > r *( c+1 ) > 2 * r ;
即: 经过两次迭代, x至少缩小一倍,算法复杂度为 2*log2(N);