“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”
给定一个整数 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
数学
n!n!n! 尾零的数量即为 n! 中因子 10 的个数,而 10=2×5,因此转换成求 n! 中质因子 2 的个数和质因子 5 的个数的较小值。
由于质因子 5 的个数不会大于质因子 2 的个数(具体证明见方法二),我们可以仅考虑质因子 5 的个数。
而 n! 中质因子 5 的个数等于 [1,n] 的每个数的质因子 5 的个数之和,我们可以通过遍历 [1,n] 的所有 5 的倍数求出。
var trailingZeroes = function(n) {
let ans = 0;
for (let i = 5; i <= n; i += 5) {
for (let x = i; x % 5 == 0; x /= 5) {
++ans;
}
}
return ans;
};
复杂度分析
-
时间复杂度:O(n)。n! 中因子 5 的个数为 O(n),具体证明见方法二。
-
空间复杂度O(1)。
优化计算
- 肯定不可能真去把 n! 的结果算出来,阶乘增长可是比指数增长都恐怖
- 两个数相乘结果末尾有 0,一定是因为两个数中有因子 2 和 5,因为 10 = 2 x 5
- 也就是说,问题转化为:n! 最多可以分解出多少个因子 2 和 5
- 举例来说,n = 25,那么 25! 最多可以分解出几个 2 和 5 相乘?这个主要取决于能分解出几个因子 5,因为每个偶数都能分解出因子 2,因子 2 肯定比因子 5 多得多
- 现在,问题转化为:n! 最多可以分解出多少个因子 5
- 假设 n = 125,来算一算 125! 的结果末尾有几个 0
- 125 / 5 = 25,这一步就是计算有多少个像 5,15,20,25 这些 5 的倍数,它们一共可以提供一个因子 5
- 像 25,50,75 这些 25 的倍数,可以提供两个因子 5,那么我们再计算出 125! 中有 125 / 25 = 5 个 25 的倍数,它们每人可以额外再提供一个因子 5
- 我们发现 125 = 5 x 5 x 5,像 125,250 这些 125 的倍数,可以提供 3 个因子 5,那么我们还得再计算出 125! 中有 125 / 125 = 1 个 125 的倍数,它还可以额外再提供一个因子 5
- 125! 最多可以分解出 25 + 5 + 1 = 31 个因子 5,也就是说阶乘结果的末尾有 31 个 0
/**
* @param {number} n
* @return {number}
*/
var trailingZeroes = function (n) {
let res = 0;
let divisor = 5;
while (divisor <= n) {
res += Math.floor(n / divisor);
divisor *= 5;
}
return res;
};