暴力列舉法很簡單,從較小整數的一班開始,試圖找到乙個合適的整數i,檢查這個整數i是否被a和b同時整除;
/**
* 暴力列舉法求最大公約數
** @param a
* @param b
* @return
*/public static int getgreatestcommondivisor_v1(int a, int b)
for (int i = smaller / 2; i > 1; i--)
}return 1;
}
注意:這個方法簡單暴力的實現了功能,但是效率不行,想想,如果傳入的整數是100001和10000,使用上述方法需要迴圈10000/2-1=4999次!效率太低,我們看看更高效點的方法——輾轉相除法。
輾轉相除法,又稱歐幾里得演算法,該演算法的目的是求出兩個正整數的最大公約數。
演算法定理:兩個正整數a和b(a>b),他們的最大公約數等於a除以b的餘數c和b之間的最大公約數.
例如10和25,25除以10商2餘5,那麼10和25的最大公約數等同與10和5的最大公約數,以此類推,逐漸把兩個較大的整數之間的運算簡化成兩個較小整數之間的運算,直到兩個資料可以整除,或著其中乙個整數小到1為止.根據定理描述,我們可以使用遞迴的方法把問題逐步簡化.
/**
* 輾轉相除法求最大公約數
** @param a
* @param b
* @return
*/public static int getgreatestcommondivisor_v2(int a, int b)
return getgreatestcommondivisor_v2(bigger % smaller, smaller);
}
注意:當兩個整數較大時,做a%b取模運算的效能會比較差,我們試試看能不能不取模,試試《九章算術》——更相減損術
原理:兩個正整數a和b(a>b),他們的最大公約數等於a-b的差值c和較小數b的最大公約數
由此,我們同樣使用遞迴的方式來簡化問題.首先,計算出a和b的差值c(假設a>b),把問題轉化成求c和b的最大公約數;然後計算出c和b的差值d(假設c>b),把問題轉化成求d和b的最大公約數,就這樣一致轉化下去.......逐漸把兩個較大的整數之間的運算簡化成兩個較小整數之間的運算,直到兩個數可以相等為止,最大公約數就是最終相等的這兩個數的值.
/**
* 使用更相減損術求最大公約數
* @param a
* @param b
* @return
*/public static int getgreatestcommondivisor_v3(int a, int b)
int bigger = a > b ? a : b;
int smaller = a < b ? a : b;
return getgreatestcommondivisor_v3(bigger-smaller,smaller) ;
}
注意:更相減損術根據兩數之差的方式遞迴,運算次數肯定遠大於輾轉相除法.更相減損術是不穩定的演算法,當兩數相差懸殊時,如計算100000和1的最大公約數,就要遞迴99999次!什麼方法可以避免取模運算又能儘量減少運算次數呢,我們可以試試下面這個方法.
優點:把輾轉相除法和更相減損術的優勢相結合,在更相減損術的基礎上使用位移運算.
當a和b均為偶數時,getgreatestcommondivisor_v4(a,b)=2*getgreatestcommondivisor_v4(a/2,b/2)=2*getgreatestcommondivisor_v4(a>>1,b>>1);
當a為偶數,b為奇數時,getgreatestcommondivisor_v4(a,b)=getgreatestcommondivisor_v4(a/2,b)=getgreatestcommondivisor_v4(a>>1,b);
當a為奇數,b為偶數時,getgreatestcommondivisor_v4(a,b)=getgreatestcommondivisor_v4(a,b/2)=getgreatestcommondivisor_v4(a,b>>1);
當a,b均為奇數時,先利用更相減損術運算一次,getgreatestcommondivisor_v4(a,b)=getgreatestcommondivisor_v4(b,a-b),此時a-b必然是偶數,然後有可以繼續位移運算了.
/**
* 更相減損術與位移相結合
* @param a
* @param b
* @return
*/public static int getgreatestcommondivisor_v4(int a, int b)
if((a&1)==0 && (b&1)==0)else if((a&1)==0 && (b&1)!=0)else if((a&1)!=0 && (b&1)==0)else
}
1.暴力列舉法:時間複雜度為o(min(a,b));
2.輾轉相除法:時間複雜度不好計算,可以近似為o(log(max(a,b))),但是取模運算效能較差;
3.更相減損術:避免了取模運算,但是演算法效能不穩定,最壞時間複雜度為o(max(a,b));
4.更相減損術與位移相結合:不但避免了取模運算,而且演算法效能穩定,時間複雜度為o(log(max(a,b)));
求最大公約數
最新用了三種演算法實現了求最大公約數的演算法,用的c 寫的,最大公約數也是我們生活中常見的問題 1 窮舉法 主要 如下 if a b for i 1 i a i 演算法分析 窮舉法先將a,b兩值比較大小並且互換,再進行與各種數的整除,如果這個數能同時被a,b整除,那麼這個數就為最大公約數,這種演算法...
求最大公約數
1.輾轉相除法 a.具體思路 兩個正整數a和b a b 它們的最大公約數等於a除以b的餘數c和b之間的最大公約數。比如10和25,25除以10商2餘5,那麼10和25的最大公約數,等同於10和5的最大公約數。有點類似動態規劃的思想,逐步減小問題規模,最後求到問題的解。int test1 int a,...
求最大公約數
輾轉相除法 輾轉相除法是求兩個自然數的最大公約數的一種方法,也叫歐幾里德演算法。例如,求 319,377 319 377 0 餘319 319,377 377,319 377 319 1 餘58 377,319 319,58 319 58 5 餘29 319,58 58,29 58 29 2 餘0 ...