最大公约数:暴力破解与辗转相除

最大公约数

解法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:欧几里得算法

思想:

image-20210313084538164

代码:

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))

posted @ 2021-03-13 08:47  记录学习Blog  阅读(97)  评论(0编辑  收藏  举报