给定一个整数 n ,返回 n! 结果中尾随零的数量。
提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1
示例 1:
输入:n = 3
输出:0
解释:3! = 6 ,不含尾随 0
示例 2:
输入:n = 5
输出:1
解释:5! = 120 ,有一个尾随 0
示例 3:
输入:n = 0
输出:0
提示:
0 <= n <= 104
二、思路
- 首先最简单的办法是直接计算阶乘,但是由于数太大会导致溢出,那么我们可以用个小技巧,只保留末尾的几位数进行计算,因为前面的数并不会影响最末尾0的个数。
- 然后我们可以进行优化,我们发现在末尾增加一个0是由于数乘上了10 = 2 x 5, 那么每当一个阶乘黎曼出现了 2 x 5,末尾便会多上一个0,于是题目转化为求解2x5的对数。直观上分析,2的个数肯定是多于5的,那么我们只需要求解5的个数。如何快速求解呢,可以通过观察阶乘来发现规律。如
1
∗
2
∗
3
∗
4
∗
(
1
∗
5
)
∗
.
.
.
∗
(
2
∗
5
)
.
.
∗
(
3
∗
5
)
.
.
.
∗
(
4
∗
5
)
.
.
.
∗
(
1
∗
5
∗
5
)
.
.
.
∗
(
6
∗
5
)
.
.
.
∗
(
2
∗
5
∗
5
)
.
.
.
1 * 2 * 3 * 4 * (1 * 5) * ... * (2 *5) .. * (3 *5) ... * (4 * 5)... * (1 * 5*5)... * (6 * 5) ... * (2 * 5 * 5)...
1∗2∗3∗4∗(1∗5)∗...∗(2∗5)..∗(3∗5)...∗(4∗5)...∗(1∗5∗5)...∗(6∗5)...∗(2∗5∗5)...
可以发现每5位数便会出现一个5,那么直接计算 n / 5 n/5 n/5就可以了,但是当n=25时,这时候又会多出现一个5,于是还要统计 n / 25 n /25 n/25, 同理可以发现125时又会多一个5,再加上一个 n / 125 n / 125 n/125, 这里可以使用递归来方便求解。
- 直接计算阶乘
class Solution {
public:
int trailingZeroes(int n) {
int ans = 0, last = 1;
for (int i = 2; i <= n; i++) {
last *= i;
while (last % 10 == 0) {
last /= 10;
ans++;
}
last %= 100000;
}
return ans;
}
};
- 计算因子5的个数
class Solution {
public:
int trailingZeroes(int n) {
return n >= 5 ? n / 5 + trailingZeroes(n / 5) : 0;
}
};