看上去简单,但是写出logarithmic time complexity的代码还是需要一些思考的。分析在下面的代码注释中。
//计算包含的2和5组成的pair的个数就可以了,一开始想错了,还算了包含的10的个数
//因为5的个数比2少,所以2和5组成的pair的个数由5的个数决定。
//观察15! = 有3个5(来自其中的5, 10, 15), 所以计算n/5就可以
但是25! = 有6个5(有5个5来自其中的5, 10, 15, 20, 25, 另外还有1个5来自25=(5*5)的另外一个5)
所以除了计算n/5, 还要计算n/5/5, n/5/5/5, n/5/5/5/5, ..., n/5/5/5,,,/5直到商为0
我的代码
class Solution {
public:
int trailingZeroes(int n) {
int count_five = 0;
while(n){
int k = n / 5;
count_five += k;
n = k;
}
return count_five;
}
};
参考:http://blog.csdn.net/feliciafay/article/details/42336835
对时间复杂度的名词解释备忘在这里。
还有一种相似的思路
O(logn)解法:
一个更聪明的解法是:考虑n!的质数因子。后缀0总是由质因子2和质因子5相乘得来的。如果我们可以计数2和5的个数,问题就解决了。考虑下面的例子:
n = 5: 5!的质因子中 (2 * 2 * 2 * 3 * 5)包含一个5和三个2。因而后缀0的个数是1。
n = 11: 11!的质因子中(2^8 * 3^4 * 5^2 * 7)包含两个5和三个2。于是后缀0的个数就是2。
我们很容易观察到质因子中2的个数总是大于等于5的个数。因此只要计数5的个数就可以了。那么怎样计算n!的质因子中所有5的个数呢?一个简单的方法是计算floor(n/5)。例如,7!有一个5,10!有两个5。除此之外,还有一件事情要考虑。诸如25,125之类的数字有不止一个5。例如,如果我们考虑28!,我们得到一个额外的5,并且0的总数变成了6。处理这个问题也很简单,首先对n÷5,移除所有的单个5,然后÷25,移除额外的5,以此类推。代码如下:
class Solution {
public:
int trailingZeroes(int n) {
int count_five = 0;
long long k = 5; //如果这里将k定义为int,则会出现TLE,因为k不停的乘5,可能会超过int所能表示的最大值,然后被截断为32为int型,然后res一直不会为0
int res = n / k;
while(res){
count_five += res;
k *= 5;
res = n / k;
}
return count_five;
}
};
转自:http://bookshadow.com/weblog/2014/12/30/leetcode-factorial-trailing-zeroes/