设计一个算法,计算出n阶乘中尾部零的个数
样例
11! = 39916800,因此应该返回 2.
这其实是一个数学题,思路倒是很简单,主要就是找每个数有多少个5的因子(只要有5的因子,因为是阶乘,就能保证有数和5匹配乘之后是0(有大量的2,4,6,8))。只有一个5的因子的数好说,只要找到一个这样的数,计数器加1就行了,但是像25,75,100这样有两个5的因子的数,还有像3125这样有四个5的因子的数怎么处理才是难点所在,很容易想到的一个方法是遍历所有能被5整除的数,起始为5,每次加5,然后判断这个数可以被5整除多少次,这样的时间复杂度是很高的,数越大时间复杂度越高,不出意外超出了时间限制,数比较小的话还是可以用这种方法的:
long long trailingZeros(long long n) {
long long res=0;
if(n<5)
return 0;
for(int i=5;i<=n;i=i+5)
{
int j=i;
while(j%5==0)
{
res++;
j/=5;
}
}
return res;
// write your code here, try to do it without arithmetic operators.
}
百度了下找到另外一种解法:是这么来的,就一直除以5,上面说了,我们主要要找到有多少个5,就是这个数可以分解成多少个5来,那么一直除就可以了,比如105,里包含了多少5,105/5=21,共有21个5,这是末尾是5或0的数目,21里还有4个5,21/5=4,这是有两个因式5的数目(不是很理解),4里面就没有5了,这样算下来应该是所以应该是21+4=25个0,以此类推:
在振哥的指导下理解了这种思路了,其实还是自己懒得在纸上画一下,画一下应该也能发现这样的规律,以105阶乘为例:
105=(1,2,3,4,5,6...105)
=5^21(1,2,3,4,5....21,.... 1,2,3,4,6,7,8,9...)
=5^21 * 5^4(1,2,3,4.....)
省略号之前的都是除以5之后还能连续起来的,后面的就不再有5整倍数了,这样看来这实际上是一个递归了。
long long trailingZeros(long long n)
{
long long res=0;
while(n/5>0)
{
res+=(n/5);
n/=5;
}
return res;
}
over