编程之美___最大公约数问题

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

看《编程之美》这本书,写的很不错,可是只看不把代码敲一下,总觉得不是真正的吸收了,而在敲代码的过程中说不定也会有更深层次的了解,所以就把其中的思路写下来同时也方便以后查阅。

PS:这篇博文是自己码的,里面的思想几乎全部都是摘抄自《编程之美》这本书,喜欢这本书,请买原书。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


写一个程序,求两个非负整数的最大公约数(greatest common divisor),如果两个正整数都很大呢,如果两个数差别比较大呢


首先求最大公约数一般是使用辗转相除法,代码如下:

int gcd1(int a, int b)
{
	if (b == 0)
	{
		return a;
	}
	return gcd1(b, a%b);
}

上述代码是根据辗转相除的定义来的,里面有%操作,对于大数来说,这是很费时的操作,有没有不用%的思路呢?

其实,(x, y) 和 (x-y, y)是相等的()表示求两个数的最大公约数,当然这里需要x > y,当x < y 时候,可以实用 y-x 来保证满足题意。

代码如下:

int gcd2(int a, int b)
{
	if (0 == b)
	{
		return a;
	}
	if (a < b)
	{
		return gcd2(b, a);
	}
	return gcd2(a-b, b);
}

把%运算换成了-运算,本质上其实没有多大变化,gcd2也有问题,如当a 和 b相差比较大的时候(如222222 和 1)求公约数的过程中将递归很深而使得程序崩溃

有没有可能结合gcd1 和 gcd2的思路呢?分析如下:

我们知道,如果x = k *a, y = k*b 那么(x,  y)= k * (a,  b)并且若 x = p*x1,p为素数且y%p != 0的话(x, y)  = (x1, y)。那么使用最小的素数2便可以有下分析

  1. x, y 均为偶数 则 (x, y) = 2 * (x  >> 1,  y  >> 1) 
  2. x为偶数,y为奇数 则 (x, y) =  (x  >> 1,  y ) 
  3. x为奇数,y为偶数 则 (x, y) =  (x ,  y  >> 1)
  4. x为奇数,y为奇数 则 (x, y) =  (x  - y,  y )
代码如下:
int gcd3(int a, int b)
{
	if (0 == b)
	{
		return a;
	}
	if (a < b)
	{
		return gcd3(b, a);
	}
	if (a&1)
	{
		if (b&1)
		{
			return gcd3(a-b, b);
		}
		else
		{
			return gcd3(a, b >> 1);
		}
	}
	else
	{
		if (b&1)
		{
			return gcd3(a >> 1, b);
		}
		else
		{
			return 2 * gcd3(a >> 1, b >> 1);
		}
	}
}

通过移位和减法来避免取模运算,提高了算法的效率。


PS: 这里的示例代码都是用int来说明问题,可以轻易地推广到大数问题,只有重载相应的运算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值