程式設計之美7:最大公約數
阿新 • • 發佈:2018-11-27
1:輾轉相除法
f(x,y) = f(y, x%y);
int gcd(int x, int y)
{
return (!y) ? x : gcd(y, x % y);
}
2:對於大整數,取模運算非常昂貴。 f(x, y) = f(x-y, y); BigInt gcd(BigInt x, BigInt y) { if (x < y) { return gcd(y, x); } if (y == 0) { return x; } else { return gcd(x-y, y); } } 缺點:減法的迭代次數太多
3:找規律 (1):f(y,x) = k * f(y1,x1); 其中y = k*y1, x = k*x1; (2):f(x,y) = f(p*x1, y) = f(x1,y); 其中x=p*x1,假設p是素數,並且y%p!=0 取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)之後,(x-y)是一個偶數,下一步一定會有除以2的操作 因此,最壞情況下時間複雜度O(log2為底(max(x,y)))。 巧妙的利用位移運算和減法運算,避開了大整數除法,提高了演算法的效率。 BigInt gcd(BigInt x,BigInt y) { if (x < y) { return gcd(y, x); } if (y == 0) { return x; } else { if (IsEven(x)) { if (IsEven(y)) { return (gcd(x >> 1, y >> 1) << 1); } else { return gcd(x >> 1, y); } } else { if (IsEven(y)) { return gcd(x, y >> 1); } else { return gcd(y, x - y); } } } }