我们用辗转相除法(又称欧几里得算法)来计算两个数的最大公约数 (Greatest Common Divisor)所以下文用gcd(a,b)表示a和b的最大公约数。

先举一个例子: 假如需要求 434 和 652 的最大公约数,用欧几里得算法,是这样进行的: 434 / 652 = 0 (余 434) 652 / 434 = 1(余218) 434 / 218 = 1(余216) 218 / 216 = 1 (余2) 216 / 2 = 108(余0) 以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数,所以就得出了 434 和 652 的最大公约数 2。

算法的核心其实是gcd(a,b)=gcd(b,amodb)gcd(a,b) = gcd(b,a \bmod b) (即:aabb 的最大公约数等于 aaa%ba\%b 的最大公约数。这个性质在本文最后会给出证明) 然后我们考虑,对于两个数 aba、b , 如果a%b==0a\%b==0的话,那这两个数的最大公约数是 bb 这样的话代码我们就可以直接写出来了。

c++

class Solution {
public:
    int gcd(int a, int b) {
        if(a%b==0){return b;}
        else{return gcd(b,a%b);}
    }
};

java

import java.util.*;
public class Solution {
    public int gcd (int a, int b) {
        if(a%b==0){return b;}
        else{return gcd(b,a%b);}
    }
}

python

class Solution:
    def gcd(self , a , b ):
        if a%b==0:
            return b
        else:
            return self.gcd(b,a%b)

gcd(a,b)=gcd(b,amodb)gcd(a,b) = gcd(b,a \bmod b) 的证明: 我们只需要证明gcd(a,b)=gcd(b,ab)gcd(a,b) = gcd(b,a -b),就可以满足gcd(a,b)=gcd(b,ab)=gcd(b,abb)=gcd(b,ab...b)=gcd(b,amodb)gcd(a,b) = gcd(b,a -b) = gcd(b,a-b-b) = gcd(b,a-b...-b) = gcd(b,a \bmod b) 下面我们来证明gcd(a,b)=gcd(b,ab)gcd(a,b) = gcd(b,a -b): 设 gcd(a,b)=cgcd(a,b)=c 我们先证明 ccbbaba-b 的公约数: 那么a=k1×ca = k_1\times c , b=k2×cb = k_2\times c ab=(k1k2)×ca - b = (k_1-k_2)\times c k1,k2,k3,k4k_1,k_2,k_3,k_4 为正整数 这样就可以推出,ccbbaba-b 的公约数

下面我们来证明 ccbbaba-b 的最大公约数: 假设 gcd(b,ab)gcd(b,a-b)dd 不是 cc ,那么 d>cd>c b=k3×db = k_3\times d , ab=k4×da-b = k_4 \times d a=(k3+k4)d\Rightarrow a = (k_3+k_4)d \Rightarrow d是a和b的共同因子,但gcd(a,b)=cgcd(a,b)=c,则dcd\leq c,与d>cd>c矛盾,所以假设不成立,得证ccbbaba-b 的最大公约数: