求最大公約數的若干個方法:
暴力枚舉
輾轉相除法(歐幾里得算法)
更相減損法(九章算術)
- 上兩種方法的結合
優化版本
public class GCD {
/**
* 2 * x == k, 或者 2 * x + 1 == k
* 既然要求最大公約數,我們就從最大的數開始,
* 那麼就如上面所示,最先從x開始考慮
* @param a
* @param b
* @return
*/
public static int gcd(int a, int b) {
int big = Math.max(a, b);
int small = Math.min(a, b);
if(big % small == 0) {
return small;
}
for(int i = small >> 1 ; i > 1 ; i--) {
if(small % i == 0 && big % i == 0) {
return i;
}
}
return 1;
}
/**
* 輾轉相除法(歐幾里得算法)
*
* 如果算法入口處 a < b,例如 5, 25
* 則這個算法會自動將5,25進行交換
* gcd1(5, 25) = gcd1(25, 5 % 25) = gcd1(25, 5)
*
* 而總是有b > a % b,所以這個算法總能夠保證 a >= b
* @param a
* @param b
* @return
*/
public static int gcd1(int a, int b) {
return b == 0 ? a : gcd1(b, a % b);
}
/**
* 更相減損法
* @param a
* @param b
* @return
*/
public static int gcd2(int a, int b) {
if(a == b) {
return a;
}
int big = Math.max(a, b);
int small = Math.min(a, b);
return gcd2(big-small, small);
}
/**
* a, b均爲偶數, 則 gcd(a, b) = 2 * gcd(a/2, b/2) = gcd(a >> 1, b >> 1) << 1;
* a爲奇數,b爲偶數,則 gcd(a, b) = gcd(a, b >> 1)
* a爲偶數,b爲奇數 則 gcd(a, b) = gcd(a >> 1, b)
* a,b均爲奇數, 則 gcd(a, b) = gcd(a - b, b) {假設a >= b}
* @param a
* @param b
* @return
*/
public static int gcd3(int a, int b) {
if(a == b) {
return a;
}
if((a & 1) == 0 && (b & 1) == 0) {
return gcd3(a >> 1, b >> 1) << 1;
} else if((a & 1) == 0 && (b & 1) != 0) {
return gcd3(a >> 1, b);
} else if((a & 1) != 0 && (b & 1) == 0) {
return gcd3(a, b >> 1);
} else {
int big = Math.max(a, b);
int small = Math.min(a, b);
return gcd3(big-small, small);
}
}
public static void main(String[] args) {
System.out.print(gcd(25, 5) + " ");
System.out.print(gcd(100, 80) + " ");
System.out.println(gcd(27, 14));
//
System.out.print(gcd1(25, 5) + " ");
System.out.print(gcd1(100, 80) + " ");
System.out.println(gcd1(27, 14));
//
System.out.print(gcd2(25, 5) + " ");
System.out.print(gcd2(100, 80) + " ");
System.out.println(gcd2(27, 14));
//
System.out.print(gcd3(25, 5) + " ");
System.out.print(gcd3(100, 80) + " ");
System.out.println(gcd3(27, 14));
}
}