一、题目
1、题目描述
给定一个整数
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 ≤ \leq ≤ n ≤ \leq ≤ 1 0 4 10^4 104
2、基础框架
- Java版本给出的基础框架代码如下:
class Solution {
public int trailingZeroes(int n) {
}
}
3、原题链接
二、解题报告
1、方法一:数学
1. 思路分析
(
1
)
(1)
(1) 首先不考虑计算出阶乘,再通过模运算得到尾随零。因为阶乘的增长速度是呈指数级的,从
13
!
13!
13! 开始,
4
4
4 字节的 int
类型就已经无法存储阶乘的结果了;从
21
!
21!
21! 开始,
8
8
8 字节的 long
类型也已经无法存储阶乘的结果了。
(
2
)
(2)
(2)
n
!
n!
n! 尾零的数量即为
n
!
n!
n! 中因子
10
10
10 的个数,而
10
=
2
×
5
10=2×5
10=2×5,因此转换成求
n
!
n!
n! 中质因子
2
2
2 的个数和质因子
5
5
5 的个数的较小值。
(
3
)
(3)
(3) 由于质因子
5
5
5 的个数不会大于质因子
2
2
2 的个数(具体证明见方法二),我们可以仅考虑质因子
5
5
5 的个数。而
n
!
n!
n! 中质因子
5
5
5 的个数等于
[
1
,
n
]
[1,n]
[1,n] 中的每个数的质因子
5
5
5 的个数之和,我们可以通过遍历
[
1
,
n
]
[1,n]
[1,n] 的所有
5
5
5 的倍数求出。
2. 复杂度分析
空间复杂度:
O
(
n
)
O(n)
O(n)。
n
!
n!
n!中
5
5
5 的个数为
O
(
n
)
O(n)
O(n),具体证明见方法二。
时间复杂度:
O
(
1
)
O(1)
O(1)。
3. 代码详解
class Solution {
public int trailingZeroes(int n) {
int count = 0;
for(int i = 5; i <= n; i+=5){
for(int j = i; j % 5 == 0; j /= 5){
count++;
}
}
return count;
}
}
2、方法二:优化计算
1. 思路分析
(
1
)
(1)
(1) 换一个角度考虑
[
1
,
n
]
[1,n]
[1,n] 中质因子
p
p
p 的个数。
[
1
,
n
]
[1,n]
[1,n] 中
p
p
p 的倍数有
n
1
=
⌊
n
p
⌋
n_1 = \lfloor {\frac {n} {p}} \rfloor
n1=⌊pn⌋ 个,这些数至少贡献出了
n
1
n_1
n1 个质因子
p
p
p 。
p
2
p^2
p2 的倍数有
n
2
=
⌊
n
p
2
⌋
n_2=\lfloor {\frac {n} {p^2}} \rfloor
n2=⌊p2n⌋ 个,由这些已经是
p
p
p 的倍数了,为了不重复统计
p
p
p 的个数,仅考虑额外贡献的质因子个数,即这些数额外贡献了至少
n
2
n_2
n2 个质因子
p
p
p 。
(
2
)
(2)
(2) 以此类推,
[
1
,
n
]
[1,n]
[1,n] 中质因子
p
p
p 的个数为
∑
k
=
1
∞
⌊
n
p
k
⌋
\sum\limits_{k=1}^{\infty} \lfloor {\frac {n} {p^k}} \rfloor
k=1∑∞⌊pkn⌋
上式表明:
1.
n
n
n 不变,
p
p
p 越大,质因子
p
p
p 的个数越少,因此
[
1
,
n
]
[1,n]
[1,n] 中质因子
5
5
5 的个数小于 质因子
2
2
2 的个数;
2.
[
1
,
n
]
[1,n]
[1,n]中质因子5的个数为
∑
k
=
1
∞
⌊
n
5
k
⌋
<
∑
k
=
1
∞
n
5
k
=
n
4
=
O
(
n
)
\sum\limits_{k=1}^{\infty} \lfloor {\frac {n} {5^k} } \rfloor < \sum\limits_{k=1}^{\infty} {\frac {n} {5^k} } = \frac{n}{4} = O(n)
k=1∑∞⌊5kn⌋<k=1∑∞5kn=4n=O(n)
(
3
)
(3)
(3) 代码实现时,由于
⌊
n
5
k
⌋
=
⌊
n
p
k
−
1
5
⌋
\lfloor {\frac {n} {5^k} } \rfloor = \lfloor {\frac{\frac{n}{p^{k-1}}}{5}} \rfloor
⌊5kn⌋=⌊5pk−1n⌋
因此我们可以通过不断将
n
n
n 除以
5
5
5 ,并将除后的结果累加赋给
n
n
n,来得到答案。
2. 复杂度分析
空间复杂度:
O
(
n
)
O(n)
O(n)。
时间复杂度:
O
(
1
)
O(1)
O(1)。
3. 代码详解
class Solution {
public int trailingZeroes(int n) {
int count = 0;
while(n >= 5){
n /= 5;
count += n;
}
return count;
}
}