題目:寫一段**,求兩個數的最大公約數,盡量優化演算法的效能。
方案1:輾轉相除法
基於該定理,我們可以首先計算出a除以b的餘數c,把問題轉化成求b和c的最大公約數,然後計算出b除以c的餘數d,把問題轉化成求c和d的最大公約數;再計算出c除以d的餘數e,把問題轉換成求d和e的最大公約數…以此類推,逐漸把兩個較大整數之間的運算簡化成兩個較小整數之間的運算,直到兩個數可以整除,或者其中乙個數減小到1為止。
**實現:
/**
* 輾轉相除法求最大公約數
* @param a @param b 求a和b的最大公約數
* @return 返回最大公約數
*/public
static
intgetgreatestcommondivisor
(int a,
int b)
return
getgreatestcommondivisor
(big%small,small)
;}
缺點:輾轉相除法在兩個數較大時,進行取模運算(%)效能會比較差。
方案2:更相減損術
基於該定理:首先計算出a和b的差值c,把問題轉化為求b和c的最大公約數;然後計算出c和b的差值d,計算出…以此類推,逐漸把兩個較大整數之間的運算簡化為兩個較小整數之間的運算,直到兩個數可以相等為止,最大公約數就是最終相等的這兩個數的值。
**實現:
//更相減損術求最大公約數
public
static
intgetgreatestcommondivisor
(int a,
int b)
int big=a>b?a:b;
int small=areturn
getgreatestcommondivisor
(big-small,small)
;}
缺點:更相減損術利用兩數求差的方式進行遞迴,其運算次數遠遠大於輾轉相除法。
最終方案:
具體步驟:
當a和b均為偶數時,getgreatestcommondivisor(a,b)=2*getgreatestcommondivisor(a/2,b/2)=2*getgreatestcommondivisor(a>>1,b>>1)
;
當a為偶數,b為奇數時,getgreatestcommondivisor(a,b)=2*getgreatestcommondivisor(a/2,b)=2*getgreatestcommondivisor(a>>1,b)
;
當a為奇數,b為偶數時,getgreatestcommondivisor(a,b)=2*getgreatestcommondivisor(a,b/2)=2*getgreatestcommondivisor(a,b>>1)
當a和b均為奇數時,先利用更相減損術計算一次,getgreatestcommondivisor(a,b)=2*getgreatestcommondivisor(b,a-b)
,此時a-b必然是偶數,然後又可以繼續進行以移位計算。
時間複雜度:o(max(a,b))
**實現:
//最終方案:移位運算
public
static
intgetgreatestcommondivisor
(int a,
int b)if(
(a&1)==
0&&(b&1)==
0)elseif(
(a&1)==
0&&(b&1)!=
0)elseif(
(a&1)!=
0&&(b&1)==
0)else
}
時間複雜度:o(log(max(a,b))) 最大公約數簡便演算法 最大公約數演算法
1 查詢約數法 先分別找出每個數的所有約數,再從兩個數的約數中找出公有的約數,其中最大的乙個就是 最大公約數 例如,求 12 和 30 的最大公約數 12 的約數有 1 2 3 4 6 12 30 的約數有 1 2 3 5 6 10 15 30 12 和 30 的公約數有 1 2 3 6,其中 6 ...
求最大公約數
最新用了三種演算法實現了求最大公約數的演算法,用的c 寫的,最大公約數也是我們生活中常見的問題 1 窮舉法 主要 如下 if a b for i 1 i a i 演算法分析 窮舉法先將a,b兩值比較大小並且互換,再進行與各種數的整除,如果這個數能同時被a,b整除,那麼這個數就為最大公約數,這種演算法...
求最大公約數
暴力列舉法很簡單,從較小整數的一班開始,試圖找到乙個合適的整數i,檢查這個整數i是否被a和b同時整除 暴力列舉法求最大公約數 param a param b return public static int getgreatestcommondivisor v1 int a,int b for in...