python最大公约数和最小公倍数的求法_最大公约数和最小公倍数的求法分析
簡介
求最大公約數和最小公倍數可能是編程中最常見的幾個基本問題了。因為他們的基本概念基本上很早的時候就知道了,對他們的求法和他們之間的關系都比較有意思。
基本的數學性質
先從最大公約數這一部分開始吧。從本身的概念來理解的話,就是說假設D = gcd(A, B),那么對于A和B這兩個數來說,D是他們之間最大的公共因子。假設A > B, 那么既然D是他們的因子,A可以表示成A = SD, B可以表示成B = KD.(S > K)。
方法一:
那么,假設給定兩個數A,B。我們怎么來求他們的最大公約數呢?一種最直接簡單的方法如下:
1.首先對每個數A, B分別求他們的因子,并將這些可以整除的因子保存到一個數組里面。因為之需要計算到最大為該數的求根,所有耗費的計算量分別為根號A和根號B.
2. 通過遍歷比較兩個保存因子的數組,找到相同且最大的一個,那么這個就是所期望的結果。這一步所需要耗費的時間也是根號N級別的。
總的來說,這種方法的時間復雜度和空間復雜度都為
.
這種方法相對比較簡單,具體實現代碼就不贅述。
方法二:
另外一個典型的求法就是利用歐拉算法,也就是說,要利用gcd(A, B) = gcd(A-B, B)這一步的特性。假設A>B的情況,那么可以多次采用gcd(A, B) = gcd(A-B, B)這一規則,然后直到一方的數字減少到0.那么最后剩下的另外一個數就是我們要求的最大公約數。
前面提出這么個步驟還有一定的優化的地方。假設A>B,經過若干次的運算后,使得A-NB < B,此時,不等式左邊的結果值相當于A mod B。也就是說,gcd(A, B) = gcd(A mod B, B) = gcd(B, A mod B). 那么,根據前面的這種推導關系,我們可以得出如下的一個實現方法:
public static long gcd(long a, long b)
{
if(b == 0)
return a;
else
return gcd(b, a % b);
}
前面數學的定義就形成了一個很好的遞歸關系。如果我們想將前面的遞歸實現轉換成非遞歸的實現的話,需要考慮的就是每次兩個數字都要將與對方求模的結果賦給自己,然后比較結果是否為0,如果是則返回另外一個數字。
非遞歸版本的實現代碼如下:
public static long gcdIter(long a, long b)
{
if(b == 0)
return a;
while(true)
{
a = a % b;
if(a == 0)
return b;
b = b % a;
if(b == 0)
return a;
}
}
還有另外一個版本的寫法,這個思路用python實現看起來比較簡潔,這里就一并貼出來了。最重要的是這部分代碼能夠考慮到各種特殊的情況:
def gcd(p, q):
while p != q:
if p < q:
p, q = q, p
if q == 0:
return p
p, q = q, p % q
return p
if __name__ == '__main__':
print gcd(0, 0)
print gcd(1, 0)
print gcd(0, 1)
print gcd(2, 4)
print gcd(3, 5)
最小公倍數:
前面費老勁終于整出了最大公約數的求法,那么慢著,最小公倍數該怎么求呢?實際上,通過一條有意思的數學性質,就可以通過最大公約數來求出最小公倍數來。假設用LCM(A, B)來表示最小公倍數,GCD(A, B)表示最大公約數。那么就有這樣的性質:LCM(A, B) * GCD(A, B) = AB。所以說,只要求出GCD(A, B),在用AB的結果除以最大公約數,得到的結果就是最小公約數了。呵呵,這是一個比較取巧的地方。
總結
求最大公約數和最小公倍數主要在一些數學的問題中用到,利用歐拉算法的一個改進就可以達到log(N)這個時間復雜度的計算方法。再利用他們的乘積關系,也可以很方便的求出最小公倍數來。具體歐拉算法的證明以及這個數學乘積關系的證明后面補上。:)
參考資料
總結
以上是生活随笔為你收集整理的python最大公约数和最小公倍数的求法_最大公约数和最小公倍数的求法分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “满篇都是‘吃人’二字”的出处是哪里?完
- 下一篇: vant组件实现上传图片裁剪_如何用 1