一、问题描述:在lintcode上有这么一个问题,如下图所示。设计一个算法,计算出n阶乘中尾部零的个数。
二、尝试
(1)相信很多人看到这个问题的第一个想法就是,先计算n阶乘的结果,然后对10进行求余判断,而被10整除的次数就是尾部零的个数。代码如下:
long long trailingZeros(long long n) {
// write your code here, try to do it without arithmetic operators.
//计算n阶乘
int s=1;
for(int i=1;i<=n;i++)
{
s=s*i;
}
//对结果进行判断
int num = 0;
//对10进行求余
while(s%10==0)
{
num++;
s = s/10;
}
return num;
}
看结果,说容易陷入死循环。为什么会陷入死循环呢?n才是105哎,105!等于多少?用了一个在线阶乘计算器计算发现结果很大1.0813967582402912e+168。而int是32位,数据早已溢出,所以,用于存放阶乘结果的s要改成长整型long long int。
(2)再次尝试,发现依然运行超时。看来计算n阶乘占用的空间和时间都比较长。
(3)当我们尝试从1到n逐次计算n阶乘时,会发现一个规律,遇见能被5整除的数时,尾部0就可+1;而尾部的0一共有多少个,就要看这个数包含多少个5的因子。比如1到4的阶乘结果分别为1、2、6、24,5到9的阶乘结果是120、720、5040、40320、362880,10到14的结果分别是3628800、39916800、479001600、6227020800、87178291200,然后15!=1307674368000。也就是5有一个0,10有2个0,15有3个0,20有4个0,25有6个0,30有7个0等等,代码如下
long long trailingZeros(long long n) {
// write your code here, try to do it without arithmetic operators.
//计算n阶乘
long long num = 0;
long long temp=n;
while(temp)
{
temp /= 5;
num += temp;
}
return num;
}
结果
值得注意的一件事就是,其中数据类型的定义,要是long long类型的,这一点题目在定义的时候函数结果上也有提示。
在线计算阶乘的地址http://www.99cankao.com/statistics/factorial-calculator.php