172. 阶乘后的零 : 经典统计质因数运用题

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

这是 LeetCode 上的 172. 阶乘后的零 ,难度为 中等

Tag : 「数学」

给定一个整数 n n ,返回 n ! n! 结果中尾随零的数量。

提示  n ! = n ( n 1 ) ( n 2 ) . . . 3 2 1 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 < = 1 0 4 0 <= n <= 10^4

进阶:你可以设计并实现对数时间复杂度的算法来解决此问题吗?

数学

对于任意一个 n ! n! 而言,其尾随零的个数取决于展开式中 10 10 的个数,而 10 10 可由质因数 2 5 2 * 5 而来,因此 n ! n! 的尾随零个数为展开式中各项分解质因数后 2 2 的数量和 5 5 的数量中的较小值。

即问题转换为对 [ 1 , n ] [1, n] 中的各项进行分解质因数,能够分解出来的 2 2 的个数和 5 5 的个数分别为多少。

为了更具一般性,我们分析对 [ 1 , n ] [1, n] 中各数进行分解质因数,能够分解出质因数 p p 的个数为多少。根据每个数能够分解出 p p 的个数进行分情况讨论:

  • 能够分解出至少一个 p p 的个数为 p p 的倍数,在 [ 1 , n ] [1, n] 范围内此类数的个数为 c 1 = n p c_1 = \left \lfloor \frac{n}{p} \right \rfloor
  • 能够分解出至少两个 p p 的个数为 p 2 p^2 的倍数,在 [ 1 , n ] [1, n] 范围内此类数的个数为 c 2 = n p 2 c_2 = \left \lfloor \frac{n}{p^2} \right \rfloor
  • ...
  • 能够分解出至少 k k p p 的个数为 p k p^k 的倍数,在 [ 1 , n ] [1, n] 范围内此类数的个数为 c k = n p k c_k = \left \lfloor \frac{n}{p^k} \right \rfloor

我们定义一个合法的 k k 需要满足 p k n p^k \leqslant n ,上述的每一类数均是前一类数的「子集」(一个数如果是 p k p^k 的倍数,必然是 p k 1 p^{k-1} 的倍数),因此如果一个数是 p k p^k 的倍数,其出现在的集合数量为 k k ,与其最终贡献的 p p 的数量相等。

回到本题, n ! n! 中质因数 2 2 的数量为 :

i = 1 k 1 n 2 i = n 2 + n 2 2 + . . . + n 2 k 1 \sum_{i = 1}^{k_1}\left \lfloor \frac{n}{2^i} \right \rfloor = \left \lfloor \frac{n}{2} \right \rfloor + \left \lfloor \frac{n}{2^2} \right \rfloor + ... + \left \lfloor \frac{n}{2^{k_1}} \right \rfloor

n ! n! 中质因数 5 5 的数量为 :

i = 1 k 2 n 5 i = n 5 + n 5 2 + . . . + n 5 k 2 \sum_{i = 1}^{k_2}\left \lfloor \frac{n}{5^i} \right \rfloor = \left \lfloor \frac{n}{5} \right \rfloor + \left \lfloor \frac{n}{5^2} \right \rfloor + ... + \left \lfloor \frac{n}{5^{k_2}} \right \rfloor

2 < 5 2 < 5 ,可知 k 2 k 1 k_2 \leqslant k_1 ,同时 i i 相同的每一项满足 n 5 i n 2 i \left \lfloor \frac{n}{5^i} \right \rfloor \leqslant \left \lfloor \frac{n}{2^i} \right \rfloor ,可知最终 i = 1 k 2 n 5 i i = 1 k 1 n 2 i \sum_{i = 1}^{k_2}\left \lfloor \frac{n}{5^i} \right \rfloor \leqslant \sum_{i = 1}^{k_1}\left \lfloor \frac{n}{2^i} \right \rfloor ,即质因数 5 5 的个数必然不会超过质因数 2 2 的个数。我们只需要统计质因数 5 5 的个数即可。

代码:

class Solution {
    public int trailingZeroes(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
    }
}
复制代码

class Solution:
    def trailingZeroes(self, n: int) -> int:
        return n // 5 + self.trailingZeroes(n // 5) if n else 0
复制代码
  • 时间复杂度: O ( log n ) O(\log{n})
  • 空间复杂度:忽略递归带来的额外空间开销,复杂度为 O ( 1 ) O(1)

最后

这是我们「刷穿 LeetCode」系列文章的第 No.172 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour…

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

猜你喜欢

转载自juejin.im/post/7078842951677247525