【演算法拾遺】最大公約數
轉載請註明出處:http://blog.csdn.net/ns_code/article/details/28505569
序言
求兩個正整數的最大公約數是一個很古老且很基本的問題,歐幾里得在其著作《幾何原本》中給出了高效的解法——輾轉相除法,也叫做歐幾里得演算法。下面我們來看下求最大公約數的一些方法。
方法一
我們先來看歐幾里得的輾轉相除法。原理很簡單,假設用f(x,y)表示x和y的最大公約數,我們令x>y,則有x=ky+b,如果一個數能夠同時整除x和y,則必能同時整除b和y,而能夠同時整除b和y的數也必能同時整除x和y,即x和y的公約數與b和y的公約數相同,因此二者的最大公約數也相同,則有f(x,y)=f(y,x%y),一直輾轉相除,最終當其中一個為0時,剩下的另一個就是二者的最大公約數。一個例子如下所示:
f(42,30) = f(30,12) = f(12,6) = f(6,0) = 6
輾轉相除法的程式碼實現如下:
/*
歐幾里得演算法,輾轉相除求最大公約數
*/
int MaxYue1(int a,int b)
{
//在輾轉相除之前,確保a比b大
if(a<b)
{
int temp = a;
a = b;
b = temp;
}
//輾轉相除法球最大公約數
while(b!=0)
{
int temp = a%b;
a = b;
b = temp;
}
return a;
}
該方法用到了取模運算,編譯器在執行取模運算時,會轉化為相應的除法運算,如:x%y = x - (x%y)*y,除法運算的開銷很大,尤其對於大的整數。方法二
為了避免除法運算帶來的大的開銷,我們可以用輾轉相減法來實現,同樣利用的原理如下:如果一個數能夠同時整除x和y,則它必能同時整除x-y和y,因此最大公約數f(x,y) = f(y,x-y),注意要保證左邊的數大於右邊的數,如果小於,則將二者進行交換。
輾轉相減法的實現程式碼如下:
/*
輾轉相減法求最大公約數
*/
int MaxYue2(int a,int b)
{
if(a<b)
return MaxYue2(b,a);
if(b==0)
return a;
else
return MaxYue2(b,a-b);
}
該方法雖然避免了除法操縱帶來的大的時間開銷,但是對於大的整數,也要進行很多次的相減操作,尤其遇到兩個數相差很大的情況,比如f(1000000,1)這樣的情況,迭代相減的次數就會很多。方法三
為了減少迭代的次數,我們考慮對上述演算法進行改進,很明顯,我們可以有如下結論:
1、當x、y都為偶數時,f(x,y) = 2*f(x/2,y/2)
2、當x為偶數,y為奇數時,f(x,y) = f(x/2,y)
3、當x為奇數,y為偶數時,f(x,y) = f(x,y/2)
4、當x,y多為奇數時,f(x,y) = f(y,x-y)
每一次的操作必然是以上四種情況的其中一種,且我們對乘2和除2的操作可以通過移位來完成,效率很高,很明顯這種演算法最壞情況下的時間複雜度為O(log2max(x,y))(以2為底,max(x,y)的對數),很適合對大的整數進行計算。
這種方法實現的程式碼如下;
/*
改進輾轉相減法
*/
int MaxYue3(int a,int b)
{
if(a<b)
return MaxYue3(b,a);
if(b==0)
return a;
else
{
if((a&1)==0) //a為偶數
{
if((b&1)==0) //b也為偶數
return (MaxYue3(a>>1,b>>1)<<1);
else //b為奇數
return MaxYue3(a>>1,b);
}
else //a為奇數
{
if((b&1)==0) //b為偶數
return MaxYue3(a,b>>1);
else //b也為奇數
return MaxYue3(b,a-b);
}
}
}
相關文章
- 【演算法拾遺】最大數和最小數演算法
- 最大公約數的演算法演算法
- 求最大公公約數(最大公因數)—— 歐幾里得演算法演算法
- java演算法 求最大公約數Java演算法
- 最大公約數與歐幾里得演算法演算法
- 【演算法拾遺】階乘演算法
- 最大公約數與最小公倍數演算法演算法
- 最大公約數GCDGC
- mongoose 拾遺Go
- 【JS拾遺】函式的引數JS函式
- C. 最大公約數
- 【演算法拾遺】大數相加(不開闢額外空間)演算法
- 前端技能拾遺前端
- Linux拾遺Linux
- Java Web 拾遺JavaWeb
- [MASM拾遺]OffsetASM
- 《九章算術》中的最大公約數演算法演算法
- 最大公約數和最小公倍數
- JSON實戰拾遺之數字精度JSON
- 演算法第四版-找兩個數的最大公約數演算法演算法
- 物件導向拾遺物件
- 【java web】--Ajax拾遺JavaWeb
- C語言拾遺C語言
- 演算法設計與分析:求兩個自然數的最大公約數演算法
- 【演算法拾遺】子陣列的最大乘積演算法陣列
- 【shell 指令碼】求最大公約數指令碼
- php判斷二個數最大公約數PHP
- [資料結構拾遺]字串排序演算法總結資料結構字串排序演算法
- 求多個數最大公約數、最小公倍數的一種變換演算法演算法
- golang拾遺:嵌入型別Golang型別
- docker拾遺-之再入坑Docker
- Unix廣告拾遺 by Dennis Ritchie
- C++:最小公倍數與最大公約數C++
- 最大公約數和最小公倍數--java實現Java
- python語言程式設計——求最大公約數和最小公倍數演算法Python程式設計演算法
- acwing246 區間最大公約數
- Vue.js基礎拾遺Vue.js
- PHP 使用 Kafka 安裝拾遺PHPKafka