leetcode
leetcode 151 ~ 200
阶乘后的零

阶乘后的零

难度:

标签:

题目描述

给定一个整数 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

 

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

代码结果

运行时间: 20 ms, 内存: 16.1 MB


/*
题目思路:
计算n!中尾随零的数量可以通过计算因子5的个数来完成。
利用Stream.iterate生成从5开始的数列,每次迭代乘以5,直到数列的值大于n。然后对每个元素n/k取整并求和。
*/
import java.util.stream.Stream;
public class Solution {
    public int trailingZeroes(int n) {
        return Stream.iterate(5, k -> k <= n, k -> k * 5)
                     .mapToInt(k -> n / k)
                     .sum();
    }
}
 

解释

方法:

该题解利用了数学分析的方法来计算阶乘结果中尾随零的数量。观察可知,只有当出现 2 和 5 相乘时才会产生尾随零。而 2 的数量远大于 5 的数量,因此 5 的个数决定了尾随零的数量。通过计算 n 中包含的 5 的因子数,即可得到尾随零的数量。具体做法是通过循环不断地将 n 除以 5,并累加商,直到 n 为 0 为止。

时间复杂度:

O(log n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么尾随零的数量是由因子5的数量决定而不是因子2的数量?
在计算阶乘的结果中尾随零的数量时,我们需要考虑因子2和因子5的配对。每对包含一个2和一个5的因子可以产生一个零。在大多数情况下,因子2的数量会超过因子5的数量,因为很多偶数都包含因子2,而只有每隔几个数字才有因子5(如5, 10, 15, 20等)。因此,在阶乘中,限制尾随零数量的通常是因子5的个数,因为它们比因子2更稀少。
🦆
在循环中每次将n除以5,这种方法为何能准确计算出包含的因子5的总数?
通过不断将n除以5并累加结果的方法,可以有效计算出n的阶乘中包含的因子5的总数。首次将n除以5可以计算出小于或等于n的数字中能被5整除的数量。随后,再将得到的商继续除以5,可以计算出能被25整除的数字的数量,因为这些数字中每个至少包含两个因子5。这个过程重复进行,直到商为0,可以确保计算出所有因子5的数量,包括那些因为高次幂而多次计算的情况。
🦆
是否存在一种情况下,简单地累加n除以5的结果会导致计算过或计算少尾随零的数量?
使用这种方法计算尾随零的数量是准确的,不会导致计算过或计算少。这是因为算法考虑了所有可以被5整除的数,以及能被更高次幂的5整除的数(例如25, 125等)。每次除以5实际上是在考虑不同层次的因子5,这确保了即使在包含多个5因子的情况下也不会遗漏。因此,这种方法可以准确地计算出尾随零的数量,无论n的值有多大。

相关问题

数字 1 的个数

给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。

 

示例 1:

输入:n = 13
输出:6

示例 2:

输入:n = 0
输出:0

 

提示:

  • 0 <= n <= 109

阶乘函数后 K 个零

 f(x) 是 x! 末尾是 0 的数量。回想一下 x! = 1 * 2 * 3 * ... * x,且 0! = 1 。

  • 例如, f(3) = 0 ,因为 3! = 6 的末尾没有 0 ;而 f(11) = 2 ,因为 11!= 39916800 末端有 2 个 0 。

给定 k,找出返回能满足 f(x) = k 的非负整数 x 的数量。

 

示例 1:

输入:k = 0
输出:5
解释:0!, 1!, 2!, 3!, 和 4! 均符合 k = 0 的条件。

示例 2:

输入:k = 5
输出:0
解释:没有匹配到这样的 x!,符合 k = 5 的条件。

示例 3:

输入: k = 3
输出: 5

 

提示:

  • 0 <= k <= 109