问题描述:
设计一个算法,计算出n阶乘中尾部零的个数
样例
11! = 39916800,因此应该返回 2
挑战
O(logN)的时间复杂度
解决方法:
常规思路第一步想到的是计算出n!,然而这种方法不仅计算量大,计算时间长,时间复杂度大于O(logN)。并且,更严重的问题是:会产生溢出
我们知道 long long 型的数表示的最大值是2^63-1,而阶乘很容易超过这个数,所以会产生溢出。
注意:
1、C语言中^不表示幂次方,而是位异或,幂次方正确应该是调用pow函数。
2、注意符号数和无符号数的区别。
正确方法:
分解质因素,尾数为零的情况是:尾数为5和尾数为偶数的数相乘。比如:11!=1x2x3x4x5x6x7x8x9x10x11。乘法中只要有5的倍数就会使得到的积尾数就增加一个零,因此只要算出乘数中5的个数。但是,进一步发现,乘数为25的倍数的数,与偶数(比如4)相乘得到的积尾数会增加两个0。以此类推,乘数为125的倍数的数,与偶数(比如8)相乘得到的积尾数会增加三个0 ……
由于是阶乘,所以肯定有足够的偶数满足要求。
这样,算法的思想是:循环除5,将依次得到的商加起来。代码如下:
class Solution {
public:
/*
* @param n: A long integer
* @return: An integer, denote the number of trailing zeros in n!
*/
long long trailingZeros(long long n) {
// write your code here, try to do it without arithmetic operators.
long long count=0;
while(n!=0){
n=n/5;
count+=n;
}
return count;
}
};