解法一:欧几里得的辗转相除法。f(x,y)=f(y,x%y),f(a,b)表示a,b最大公约数。
int gcd(int x,int y){
return (!y)?x:gcd(y,x%y);
}
解法二:对于大数而言,取模运算(其中用到除法)是非常昂贵的开销。用辗转减法:f(x,y)=f(x-y,y),这边需要注意的是要维持左边的数大于右边的数。
解法三:(1)对于y和x来说,如果y=k*y1,x=k*x1.那么有f(y,x)=k*f(y1,x1)。(2)如果x=p*x1,假设p是素数(必须要保证y与p最大公约数为1),并且y%p!=0(即y不能被p整除),那么f(x,y)=f(p*x1,y)=f(x1,y)。因此可以用2这个素数来进行求解:
取p = 2
若x,y均为偶数,f(x,y)=2*f(x/2,y/2)=2*f(x>>1,y>>1)
若x为偶数,y为奇数,f(x,y)=f(x/2,y)=f(x>>1,y)
若x为奇数,y为偶数,f(x,y)=f(x,y/2)=f(x,y>>1)
若x,y均为奇数,f(x,y)=f(y,x-y),那么在f(x,y)=f(y,x-y)之后(这边f中也要维护左边的数大于右边的数),(x-y)是一个偶数,下一步一定会有除以2的操作。
该方法最坏情况下的时间复杂度是O(log 2(max(x,y)))。(移位是个很好的操作,切记)