【题目】
设计一个算法,算出 n 阶乘有多少个尾随零。
示例 1:
输入: 3
输出: 0
解释: 3! = 6, 尾数中没有零。
示例 2:
输入: 5
输出: 1
解释: 5! = 120, 尾数中有 1 个零.
说明: 你算法的时间复杂度应为 O(log n) 。
来源:力扣(LeetCode)
【思路】
一、暴力法
先求出 n 的阶乘,再从个位往高位判断。但是这样算出来的数太大了,而且会超时,所以不可取。
二、计算因数2和5的个数
因为我们要计算 n! 有多少个尾随零,所以我们只需要计算因数2和5的个数(2 X 5 = 10),再比较个数,最小的数为尾随零的个数。
public int trailingZeroes(int n) {
long a = 0, b = 0;
for(long i = n; i > 1; i--) {
long op = i;
while(op % 5 == 0) {
a++;
op /= 5;
}
while(op % 2 == 0) {
b++;
op /= 2;
}
}
return (int) (a >= b ? b : a);
}
但是呢,当输入的数字太大时,也会超时。
三、思路二的改版
我们可以发现,当输入的数字越大,2的数量远远小于5的数量,因此我们只需要计算5的数量就行了。
n! = 1 * 2 * 3 * 4 * 5 * .... * (n-1) * n
我们可以化简一下 n! ,我们会发现下面的规律:
n! = 1 * 2 * 3 * 4 * 5 * .... * (2*5) * ... * (3*5) * ...
每隔5个数就会出现一个5
每隔25个数会出现一个25,而25存在两个5,所以我们还需要计算有多少的25(n/25)
每隔125个数会出现一个125,而25存在三个5,所以我们还需要计算有多少的25(n/125)
… …
所以:
ans = n / 5 + n / 25 + n / 125 + …
简化:ans = n/5 + n / 5 / 5 + n / 5 / 5 / 5 + …
public int trailingZeroes(int n) {
int ans = 0;
while(n >= 5) {
n /= 5;
ans += n;
}
return ans;
}