題目:
寫一段代碼,求出兩個數的最大公約數,要儘量優化算法的性能。
1.暴力枚舉
2.輾轉相除法
兩個正整數a和b(a>b),他們的最大公約數等於a除以b的餘數c和d之間的最大公約數
3.更相減損術
兩個正整數a和b(a>b),他們的最大公約數等於a-b的差值c和較小數b的最大公約數。
4.將2和3結合起來
當a和b均爲偶數時,gcd(a,b) = 2 * gcd(a/2,b/2) = 2 *gcd(a>>1,b>>1)
當a爲偶數,b爲奇數時,gcd(a,b) = gcd(a/2,b) = gcd(a>>1,b)
當a爲奇數,b爲偶數時,gcd(a,b) = gcd(a,b/2) = gcd(a,b>>1)
當a和b都爲奇數時,先利用更相減損法運算一次,gcd(a,b) = gcd(b,a-b),此時a-b必然爲偶數,然後又可以繼續進行移位運算.
public class getGreatestCommon {
//使用暴力枚舉的方法,時間複雜度爲O(min(a,b))
public static int getGreatestCommonDivisor(int a,int b){
int big = a>b ? a:b;
int small = a<b ? a:b;
if(big%small == 0){
return small;
}
for(int i=small/2;i>1;i--){
if(small % i==0 && big%i==0){
return i;
}
}
return 1;
}
//當兩個整數較大時,做a%b的性能比較差
public static int getGreatestCommonDivisorV2(int a,int b){
int big = a>b ? a:b;
int small = a<b ? a:b;
if(big%small == 0){
return small;
}
return getGreatestCommonDivisorV2(big%small,small);
}
//更相減損法是不穩定的算法,當兩數懸殊的時候,就要遞歸很多次
public static int getGreatestCommonDivisorV3(int a,int b){
if(a==b){
return a;
}
int big = a>b ? a:b;
int small = a<b ? a:b;
return getGreatestCommonDivisorV3(big-small,small);
}
//最終方法是將輾轉相除法和更相減損法的優勢結合起來,在更相減損法的基礎上使用移位運算
public static int gcd(int a,int b){
if(a==b){
return a;
}
if((a&1) == 0&& (b&1) ==0){
return gcd(a>>1,b>>1)<<1;
}else if((a&1) == 0 &&(b&1)!=0){
return gcd(a>>1,b);
}else if((a&1) !=0 &&(b&1)==0){
return gcd(a,b>>1);
}else{
int big = a>b ? a:b;
int small = a<b ? a:b;
return gcd(big-small,small);
}
}
public static void main(String[] args){
System.out.println(gcd(25,5));
System.out.println(getGreatestCommonDivisorV3(25,5));
System.out.println(getGreatestCommonDivisorV2(25,5));
System.out.println(getGreatestCommonDivisor(25,5));
}
}