算法-求最大公約數

摘要:主要用到了輾轉相除法(歐幾里得算法),更相減損術。

題目:求出兩個整數的最大公約數。


方法一:


暴力枚舉的方法,試圖尋找到一個合適的整數 i,看看這個整數能否被兩個整型參數numberA和numberB同時整除。

這個整數 i 從2開始循環累加,一直累加到 numberA 和 numberB 中較小參數的一半爲止。循環結束後,上一次尋找

到的能夠被兩數整除的最大 i 值,就是兩數的最大公約數。




方法二:

輾轉相除法, 又名歐幾里得算法(Euclidean algorithm),目的是求出兩個正整數的最大公約數。它是已知最古老

的算法, 其可追溯至公元前300年前。

這條算法基於一個定理:兩個正整數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的最大公約數。




方法四:

衆所周知,移位運算的性能非常快。對於給定的正整數a和b,不難得到如下的結論。其中gcb(a,b)的意思是a,b的最大公約數函數:

當a和b均爲偶數,gcb(a,b) = 2*gcb(a/2, b/2) = 2*gcb(a>>1, b>>1)

當a爲偶數,b爲奇數,gcb(a,b) = gcb(a/2, b) = gcb(a>>1, b)

當a爲奇數,b爲偶數,gcb(a,b) = gcb(a, b/2) = gcb(a, b>>1)

當a和b均爲奇數,利用更相減損術運算一次,gcb(a,b) = gcb(b, a-b), 此時a-b必然是偶數,又可以繼續進行移位運算。

比如計算10和25的最大公約數的步驟如下:

  1. 整數10通過移位,可以轉換成求5和25的最大公約數

  2. 利用更相減損法,計算出25-5=20,轉換成求5和20的最大公約數

  3. 整數20通過移位,可以轉換成求5和10的最大公約數

  4. 整數10通過移位,可以轉換成求5和5的最大公約數

  5. 利用更相減損法,因爲兩數相等,所以最大公約數是5

在兩數比較小的時候,暫時看不出計算次數的優勢,當兩數越大,計算次數的節省就越明顯。

注:至於除二爲什麼不會破壞求最大公約數,需要思考下。基本的數學知識,如果不理解一奇一偶時爲什麼偶數除二還想等的話,可以這麼

理解,奇數的最大公約數中是不會出現2的。


注:java和python中!numberA&1都可以通過這種位運算判斷奇偶(python中代碼print(numberA&1))。但是這種位

運算判斷後返回的應該是0或1,需要再用==判斷一下。

(java中代碼System.out.println(!((numberA&1)==0));)

(python中代碼print(numberA&1==1))




最後總結一下上述所有解法的時間複雜度:

1.暴力枚舉法:時間複雜度是O(min(a, b))) 【注:不要認爲是O(min(a, b))/2) ...

2.輾轉相除法:時間複雜度不太好計算,可以近似爲O(log(max(a, b))),但是取模運算性能較差。

3.更相減損術:避免了取模運算,但是算法性能不穩定,最壞時間複雜度爲O(max(a, b)))

4.更相減損術與移位結合:不但避免了取模運算,而且算法性能穩定,時間複雜度爲O(log(max(a, b)))


注:這篇文章轉載的時候其實還有很多坑沒有細數,例如這兩個算法的驗證等。


發佈了17 篇原創文章 · 獲贊 5 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章