求一个数的最大公约数的三种思路——解题笔记

求一个数的最大公约数的三种思路——解题笔记

编程之美上的题目:求一个数的最大公约数。

这道题目有三种解题思路,总结如下:

思路一:

直接使用辗转相除法,这个不多介绍,代码如下:

// 直接辗转相除法
int gcd1(int a, int b)
{
	for(int m = a%b; m != 0; m = a%b)
	{
		a = b;
		b = m;
	}
	return b;
}

分析:辗转相除法需要用到数值之间的取余运算,这是非常耗时间的。

思路二:

改进辗转相除法中取余(除法)运算,改为减法。这里可以利用一个规律,x和y的最大公约数等于x-y和y的最大公约数。不过需要判断x和y的大小。

代码如下:

// x和y的最大公约数等于x-y和y的最大公约数
int gcd2(int a, int b)
{
	if(a < b)
		swap(a, b);  // 默认前面的数较大
	while(b)
		return gcd2(b, a-b);  // 递归
	return a;
}

分析:虽然这种方法只有减运算,用的是递归的实现形式。但是,需要递归的次数比较多,假如a和b之间相差较大,那么每次都只是相减,会迭代很多次。

思路三:

可以结合前面两个思路的优点,我们不全都是用减运算,偶尔用一次除法,不过只是除以2,即判断奇偶数,而且用移位运算实现。

代码如下:

// 通过判断奇偶数,减少迭代次数
bool isEven(int a)
{
	return (a & 1);  // 按位与来判断奇偶数
}

int gcd3(int a, int b)
{
	if(a < b)
		swap(a, b);  // 默认前面的数较大

	if(!b)
		return a; 

	if(isEven(a))  // if a is even
	{
		if(isEven(b))  // b is even at the same time
			return (gcd3(a>>1, b>>1) <<1); // note that *2
		else
			return (gcd3(a>>1, b));  // if only a is even
	}
	else
	{
		if(isEven(b))
			return gcd3(a, b>>1); // is only b is even
		else
			return gcd3(a-b, b);  // neither a or nor b is even
	}
}

分析:时间复杂度只是a和b中较大数的二进制位数,也就是O(log max(a, b))。注意其中判断是否为奇偶数用的是位运算。

时间: 2024-08-27 18:41:00

求一个数的最大公约数的三种思路——解题笔记的相关文章

C语言编程 求两个数的平均值方法(三种方法)

第一种方法是最常见的average=(a + b) / 2这种方式,求两个数的平均值 第二种方法是当 a<b 时averag=a+(b-a)/2 这里着重介绍的是第三种方法 average=(a&b) + (a^b)>>1 推导过程如下a + b = (a&b) 2 + (a^b)) --->average=((a&b)2+(a^b))/2 ---->average=(a&b) + (a^b)>>1 eg:两个数为15和515二进制

C语言--求两个数的最大公约数

问题: 求两个数的最大公约数 #include<stdio.h> #include<math.h>  main() { int a,b,c,i,j; printf("请输入三个数(数以逗号隔开):\n"); int arr[3]; int t; scanf_s("%d,%d,%d", &a,&b,&c); arr[0] = a;  arr[1] = b;  arr[2] = c; for (j = 0; j < 

C语言求两个数中最大公约数

在C语言中如何求两个数的最大公约数呢?下面用三种方法进行求解. 方法一:穷举法. 先比较两个数的大小,然后找出较小数t,最后判断t为何值时两个数都能整除,此方法效率较低. 代码如下: #include<stdio.h> int main() {      int num1,num2,temp,i;      scanf("%d%d",&num1,&num2);      if(num1>num2)      {            temp=num1

求两个数的最大公约数&amp;求N个数的最大公约数

一.求两个数的最大公约数 如何编程计算N个数的最大公约数(Greatest common divisor)呢?第一想法那便是两两计算,但是往往最简单的想法是不怎么靠谱的.下面用递归来解决.递归有一大好处,那便是递归非常符合人的思维,有时即使很复杂,但是依仗着递归的规律性,可以断定或推测出按递归做是正确的.如果说递归的性能低,我们可以采用备忘录法,用表记录过已经计算过的问题,避免二次计算,这样在一定程度上可以带来性能上的提升.我们可以先用递归实现,倘若在实际情况中发现性能问题,我们可以再进行优化.

写一个方法,求两个数的最大公约数和最小公倍数。

package homework0702; /* * 最大公约数 利用辗转相除法求解两个正整数的最大公约数 在循环中,只要除数不等于0,用较大的数除以较小的数,将小的一个数作为下一轮循环的大数,取得的余数作为下一轮循环较小的数,如此循环直到较小的数值为0,返回较大的数.即为最大公约数. 辗转相除法(欧几里得算法) 定理:两个整数的最大公约数等于其中较小的那个数和两数的相除余数的最大公约数.最大公约数(greatest common divisor)缩写为gcd. 最小公倍数 最小公倍数 = (a

求两个数的最大公约数

求两个数的最大公约数 问题:给定两个正整数a和b,求他们的最大公约数. 最简单的方法就是穷举法,如果a>b,那么依次计算1~b的所有整数是否是a和b的公约数. public static void main(String[] args) { long timer = System.currentTimeMillis(); System.out.println(getGCB(1000234234,1242342390)); System.out.println(System.currentTime

求两个数的最大公约数和最小公倍数

import java.util.Scanner; //求两个数的最大公约数,最小共倍数. public class CommonMaxDivisor { public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int m=scanner.nextInt(); int n=scanner.nextInt(); scanner.close(); CommonMaxDivisor cmd=new

求两个数的最大公约数和最小公倍数 C语言

C程序设计第八章的第一道题目,求两个数的最大公约数和最小公倍数.需要注意一下几点: 1.最大公约数和最小公倍数间的关系: 设两个数是a,b最大公约数是p,最小公倍数是q 那么有这样的关系:ab=pq 所以q=ab/p.2.任意整数和0的公约数是该整数的所有约数,所以它们的最大公约数为该整数本身.3.碾转相除法:被除数%除数=余数,如果余数不为0,就让原来的除数做为被除数,余数作为除数,再进行运算 被除数%除数=余数,直到得到的余数为0为止,此时的除数就是最大公约数. #include <stdi

求N个数的最大公约数和最小公倍数

除了分解质因数,还有另一种适用于求几个较小数的最大公约数.最小公倍数的方法 下面是数学证明及算法实现 令[a1,a2,..,an] 表示a1,a2,..,an的最小公倍数,(a1,a2,..,an)表示a1,a2,..,an的最大公约数,其中a1,a2,..,an为非负整数.对于两个数a,b,有[a,b]=ab/(a,b),因此两个数最小公倍数可以用其最大公约数计算.但对于多个数,并没有[a1,a2,..,an]=M/(a1,a2,..,an)成立,M为a1,a2,..,an的乘积.例如:[2,