一. 什么是最大公约数(GCD)
最大公约数(Greatest Common Divisor)是指两个或多个整数共有约数中最大的一个。例如:
-
12 和 18 的公约数有 1, 2, 3, 6,其中最大的是 6
-
所以 gcd(12, 18) = 6
二. 方法一:辗转相除法(欧几里得算法)
1.这是最经典的求最大公约数的方法,基于以下原理:
两个数的最大公约数等于较大数除以较小数的余数 和较小数的最大公约数
gcd(a, b) = gcd(b, a % b)
其中 a % b 表示 a 除以 b 的余数。
2.举个例子:
求 gcd(12, 18)
-
gcd(12, 18) = gcd(18, 12) // 先确保第一个数大
-
18 ÷ 12 = 1 余 6
-
gcd(18, 12) = gcd(12, 6) // 应用公式
-
12 ÷ 6 = 2 余 0
-
gcd(12, 6) = gcd(6, 0)
-
当第二个数为0时,第一个数就是答案:6
三.现在看代码的详细解释
方法1.1:循环实现
java
public static int gcd1(int a, int b) {
// 确保a >= b
if (a < b) {
int temp = a; // 临时变量保存a的值
a = b; // 把b的值赋给a
b = temp; // 把原来a的值赋给b
}
// 执行到这里,a一定是较大的数,b是较小的数
// 辗转相除
while (b != 0) { // 当b不等于0时继续循环
int remainder = a % b; // 求a除以b的余数
a = b; // 把b的值赋给a
b = remainder; // 把余数赋给b
}
return a; // 当b=0时,a就是最大公约数
}
用例子走一遍:计算 gcd1(12, 18)
-
输入 a=12, b=18
-
因为 12 < 18,交换:a=18, b=12
-
进入while循环:
-
第一次循环:b=12≠0
-
remainder = 18 % 12 = 6
-
a = 12
-
b = 6
-
-
第二次循环:b=6≠0
-
remainder = 12 % 6 = 0
-
a = 6
-
b = 0
-
-
第三次:b=0,退出循环
-
-
返回 a=6
方法1.2:递归实现
java
public static int gcd2(int a, int b) {
if (b == 0) { // 终止条件:当b=0时
return a; // a就是最大公约数
}
return gcd2(b, a % b); // 递归调用:用(b, a%b)继续计算
}
递归的思考方式:
-
把大问题分解成小问题
-
每次递归都让问题变小一点
-
直到遇到最简单的情况(b=0)
用例子走一遍:计算 gcd2(12, 18)
-
第一次调用:gcd2(12, 18)
-
b=18≠0,不返回a
-
调用 gcd2(18, 12%18) 即 gcd2(18, 12)
-
-
第二次调用:gcd2(18, 12)
-
b=12≠0
-
调用 gcd2(12, 18%12) 即 gcd2(12, 6)
-
-
第三次调用:gcd2(12, 6)
-
b=6≠0
-
调用 gcd2(6, 12%6) 即 gcd2(6, 0)
-
-
第四次调用:gcd2(6, 0)
-
b=0 ✓
-
返回 a=6
-
-
结果层层返回:6 ← 6 ← 6 ← 6
四.再看测试代码
java
public static void main(String[] args) {
int a = 12;
int b = 18;
// 测试两种方法
System.out.println("gcd1(" + a + ", " + b + ") = " + gcd1(a, b));
System.out.println("gcd2(" + a + ", " + b + ") = " + gcd2(a, b));
// 更多测试
System.out.println("\n更多测试:");
System.out.println("gcd(24, 36) = " + gcd2(24, 36)); // 应该是12
System.out.println("gcd(17, 13) = " + gcd2(17, 13)); // 两个质数,应该是1
System.out.println("gcd(100, 0) = " + gcd2(100, 0)); // 一个数为0,应该是100
}
理解:
辗转相除法就像"以大换小"的游戏:
-
用大数除以小数,得到余数
-
原来的小数变成新的"大数"
-
余数变成新的"小数"
-
重复直到余数为0
-
最后的小数就是答案
用 gcd(12, 18) 来说:
开始:大=18, 小=12
18 ÷ 12 = 1 余 6 → 新大=12, 新小=6
12 ÷ 6 = 2 余 0 → 余数为0,停止
答案就是最后的小数:6