LC 172. 阶乘后的零
题目描述
这是 LeetCode 上的 172. 阶乘后的零 ,难度为 中等。
给定一个整数 $n$ ,返回 $n!$ 结果中尾随零的数量。
提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1
示例 1:1
2
3
4
5输入:n = 3
输出:0
解释:3! = 6 ,不含尾随 0
示例 2:1
2
3
4
5输入:n = 5
输出:1
解释:5! = 120 ,有一个尾随 0
示例 3:1
2
3输入:n = 0
输出:0
提示:
- $0 <= n <= 10^4$
进阶:你可以设计并实现对数时间复杂度的算法来解决此问题吗?
数学
对于任意一个 $n!$ 而言,其尾随零的个数取决于展开式中 $10$ 的个数,而 $10$ 可由质因数 $2 * 5$ 而来,因此 $n!$ 的尾随零个数为展开式中各项分解质因数后 $2$ 的数量和 $5$ 的数量中的较小值。
即问题转换为对 $[1, n]$ 中的各项进行分解质因数,能够分解出来的 $2$ 的个数和 $5$ 的个数分别为多少。
为了更具一般性,我们分析对 $[1, n]$ 中各数进行分解质因数,能够分解出质因数 $p$ 的个数为多少。根据每个数能够分解出 $p$ 的个数进行分情况讨论:
- 能够分解出至少一个 $p$ 的个数为 $p$ 的倍数,在 $[1, n]$ 范围内此类数的个数为 $c_1 = \left \lfloor \frac{n}{p} \right \rfloor$
- 能够分解出至少两个 $p$ 的个数为 $p^2$ 的倍数,在 $[1, n]$ 范围内此类数的个数为 $c_2 = \left \lfloor \frac{n}{p^2} \right \rfloor$
- …
- 能够分解出至少 $k$ 个 $p$ 的个数为 $p^k$ 的倍数,在 $[1, n]$ 范围内此类数的个数为 $c_k = \left \lfloor \frac{n}{p^k} \right \rfloor$
我们定义一个合法的 $k$ 需要满足 $p^k \leqslant n$,上述的每一类数均是前一类数的「子集」(一个数如果是 $p^k$ 的倍数,必然是 $p^{k-1}$ 的倍数),因此如果一个数是 $p^k$ 的倍数,其出现在的集合数量为 $k$,与其最终贡献的 $p$ 的数量相等。
回到本题,$n!$ 中质因数 $2$ 的数量为 :
$n!$ 中质因数 $5$ 的数量为 :
由 $2 < 5$,可知 $k2 \leqslant k_1$,同时 $i$ 相同的每一项满足 $\left \lfloor \frac{n}{5^i} \right \rfloor \leqslant \left \lfloor \frac{n}{2^i} \right \rfloor$,可知最终 $\sum{i = 1}^{k2}\left \lfloor \frac{n}{5^i} \right \rfloor \leqslant \sum{i = 1}^{k_1}\left \lfloor \frac{n}{2^i} \right \rfloor$,即质因数 $5$ 的个数必然不会超过质因数 $2$ 的个数。我们只需要统计质因数 $5$ 的个数即可。
代码:1
2
3
4
5class Solution {
public int trailingZeroes(int n) {
return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
}
}
1 |
|
- 时间复杂度:$O(\log{n})$
- 空间复杂度:忽略递归带来的额外空间开销,复杂度为 $O(1)$
最后
这是我们「刷穿 LeetCode」系列文章的第 No.172
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!