求兩個整數的最大公約數,要盡量優化算法的性能
思路:
方法一: 輾轉相除法, 兩個正整數a,b(a>b), 它們的最大公約數 = a除以b的余數c和較小數b之間的最大公約數。
例如:10和25, 25除以10=2...5, 那么10和25的最大公約數, 等同於10和余數5的最大公約數。
方法二:更相減損術, 兩個正整數a,b(a>b), 它們的最大公約數 = a-b的差值c和較小數b之間的最大公約數。
例如:10和25, 25-10=15, 那么10和25的最大公約數, 等同於10和15的最大公約數。
兩個整數較大時候的場景,取模性能會比較差,更相減損術更適合。但如果兩個數相差懸殊,比如10000和1時,更相減損術就要遞歸9999次。此時可以用方法三
方法三: 更相減損術+移位(最優):
- 當a,b均為偶數時,gcd(a,b) = 2*gcd(a/2,b/2) = 2*gcd(a>>1,b>>1),gcd為方法名;
- 當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必然是偶數,然后又可以繼續進行移位運算
ps. >>相當於除以2,<<相當於乘以2
代碼實現:
/** * 求兩個整數的最大公約數,要盡量優化算法的性能 * * 方法一:輾轉相除法, 兩個正整數a,b(a>b), 它們的最大公約數 = a除以b的余數c和較小數b之間的最大公約數。 * 例如:10和25, 25除以10=2...5, 那么10和25的最大公約數, 等同於10和余數5的最大公約數。 * 方法二:更相減損術, 兩個正整數a,b(a>b), 它們的最大公約數 = a-b的差值c和較小數b之間的最大公約數。 * 例如:10和25, 25-10=15, 那么10和25的最大公約數, 等同於10和15的最大公約數 * 方法三: 更相減損術+移位 */ public class GreatestCommonDivisor { /** * 輾轉相除法 * @param a * @param b * @return */ public static int getGreatestCommonDivisor(int a, int b){ int min = a; int max = b; if ( a >= b ){ min = b; max = a; } if (min == 0){ return max; } int p = max % min; return getGreatestCommonDivisor(min,p); } /** * 更相減損術 * @param a * @param b * @return */ public static int getGreatestCommonDivisor2(int a, int b){ int min = a; int max = b; if ( a >= b ){ min = b; max = a; } if (min == 0){ return max; } int p = max - min; return getGreatestCommonDivisor2(min,p); } /** * 更相減損術+移位(最優) * @param a * @param b * @return */ public static int getGreatestCommonDivisor3(int a, int b){ if(a == b){ return a; } if ((a&1)==0 && (b&1)==0){ return getGreatestCommonDivisor3(a>>1,b>>1)<<1; } if((a&1)==0 && (b&1)!=0){ return getGreatestCommonDivisor3(a>>1,b); } if((a&1)!=0 && (b&1)==0){ return getGreatestCommonDivisor3(a,b>>1); } if((a&1)!=0 && (b&1)!=0){ int min = a > b ? b : a; int max = a > b ? a : b; return getGreatestCommonDivisor3(min,max-min); } return 0; } public static void main (String[] args){ System.out.println("(1) The Greatest Common Divisor is: " + getGreatestCommonDivisor(24,8)); System.out.println("(2) The Greatest Common Divisor is: " + getGreatestCommonDivisor2(24,8)); System.out.println("(3) The Greatest Common Divisor is: " + getGreatestCommonDivisor3(24,8)); } }
結果:
(1) The Greatest Common Divisor is: 8 (2) The Greatest Common Divisor is: 8
(3) The Greatest Common Divisor is: 8