算法一:欧几里得算法
算法描述:gcd(a,b)=gcd(b,a mod b)
也就是说,两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数。
证明:即证明gcd(a,b)=gcd(b,a mod b)(此处引用百度百科的证明方法)
假设a>b且a÷b=k……r,r不为0
第一步:令c=gcd(a,b),则设a=mc,b=nc
第二步:可知r=a-kb=mc-knc=(m-kn)c
第三步:根据第二步结果可知c也是r的因数
第四步:可以断定m-kn与n互素【否则,可设m-kn=xd,n=yd,(d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc,b=nc=ycd,故a与b最大公约数≥cd,而非c,与前面结论矛盾】
从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r),得证
JAVA代码:
// 欧几里得算法(辗转相除法)
public static int Euclid(int m, int n) {
int count = 1;// 定义计数变量
int r = m % n;
while(r != 0) {
m = n;
n = r;
r = m % n;
count++;
}
System.out.println("欧几里得算法:执行了" + count + "次!");
return n;
}
算法二:更相减损法
算法描述:
第一步:任意给定两个正整数,判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
示例:
gcd(15,10)=gcd(5,10)=gcd(5,5)=5
gcd(10,8)=gcd(5,4)*2=gcd(1,4)*2=gcd(1,3)*2=gcd(1,2)*2=gcd(1,1)*2=2
JAVA代码:
// 更相减损法
public static int LiuHui(int m, int n) {
int count = 0;// 定义计数变量
int num = 0;// 记录被2整除的次数
while(m % 2 == 0 && n % 2 == 0) {
m = m / 2;
n = n / 2;
count++;
num++;
}
while(m != n) {
if(m > n) {
m = m - n;
} else {
n = n - m;
}
count++;
}
for(int i = 0; i < num; i++) {
n *= 2;
}
System.out.println("更相减损法:执行了" + count + "次!");
return n;
}
算法三:穷举法
算法描述:
第一步:取两个整数的最小值赋值给t
第二步:用m除以t。如果整除,转第三步;否则,转第四步。
第三步:用n除以t。如果整除,最大公约数即为t。否则,转第四步。
第四步:t减1,转第二步。
JAVA代码:
// 穷举法
public static int Exhaustion(int m, int n) {
int count = 0;// 定义计数变量
int t;
if(m > n) {
t = n;
} else {
t = m;
}
while(t > 0) {
if(m % t == 0 && n % t == 0) {
break;
}else {
t--;
}
count++;
}
System.out.println("穷举法:执行了" + count + "次!");
return t;
}
下面测试一下关键操作的执行次数
测试代码:
// main方法
public static void main(String[] args) {
int m = 24;
int n = 44;
int euclid = Euclid(m, n);
System.out.println("最大公约数为" + euclid);
int liuHui = LiuHui(m, n);
System.out.println("最大公约数为" + liuHui);
int exhaustion = Exhaustion(m, n);
System.out.println("最大公约数为" + exhaustion);
}
测试结果:
欧几里得算法与更相减损法的区别:
1.欧几里得算法以除法求余的方式递减,更相减损术以减法的方式递减,所以当两个数字相差较大时计算次数的区别较明显。
2.从结果体现形式来看,欧几里得算法体现结果是以相除余数为0而得到,更相减损术以减数与差相等而得到
输入:m=3,n=99
输出:
(欢迎评论,指导!)