最大公约数:暴力破解与辗转相除
最大公约数
解法1:暴力破解
思路:
比如16和24,最大公约数可能是16
循环扫描1-16之间,记录最后一次公约数
for (int i = 1; i <= x; i++) {
if(x%i==0&&y%i==0) {
gcd = i;
}
}
=》稍微优化:正着1~x/2
for (int i = 1; i <= x/2; i++) {
if(x%i==0&&y%i==0) {
gcd = i;
}
}
=》再稍微优化从x/2倒着去扫描,x/2~1,逆向扫描次数一定比正着扫小,正着扫一定是x/2次。
for (int i = x/2; i >= 1; i--) {
if(x%i==0&&y%i==0) {
gcd = i;
break;
}
}
适当时机break退出循环才能比x/2次数少。
注意:如果从x/2开始或者结束,要注意一种边界情况,就是这个小数本身就是最大的公约数,下面在算的时候从x/2可能会忽略了这一种情况,所以在一开始的时候就要特别判断一下!
if(y%x == 0) {
System.out.println(x);
System.exit(0);
}
tips:交换x和y,让x最小
if(x>y) {
x=x^y;
y=x^y;
x=x^y;
}
代码:
import java.util.Scanner;
public class 最大公约数 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
// 暴力破解
int x = sc.nextInt();
int y = sc.nextInt();
//将x和y重置一下
if(x>y) {
x=x^y;
y=x^y;
x=x^y;
}else if(x==y){
//最大公约数就是x
System.exit(0);
}
int gcd = 1;
//一种边界情况,就是这个小数本身就是最大的公约数,下面在算的时候从x/2可能会忽略了这一种情况
if(y%x == 0) {
System.out.println(x);
System.exit(0);
}
for (int i = 1; i <= x; i++) {
if(x%i==0&&y%i==0) {
gcd = i;
}
}
//略微优化,两个数的最大公约数不会超过x/2
for (int i = 1; i <= x/2; i++) {
if(x%i==0&&y%i==0) {
gcd = i;
}
}
// 再稍微优化从x/2倒着去扫描,x/2~1,逆向扫描次数一定比正着扫小
for (int i = x/2; i >= 1; i--) {
if(x%i==0&&y%i==0) {
gcd = i;
break;
}
}
System.out.println(gcd);
}
}
算法效率:O(n)
解法2:欧几里得算法
思想:
代码:
public static int gcd(int x,int y) {
if(x>y) {
x = x^y;
y = x^y;
x = x^y;
}
while(y%x!=0){
int temp = y%x;
y = x;
x = temp;
gcd(x,y);
}
return x;
}
算法效率:O(log(n))