LeetCode 172. 阶乘后的零

一、题目

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、原题链接

LeetCode 172. 阶乘后的零

二、解题报告

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=1pkn
  上式表明:
    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=15kn<k=15kn=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=5pk1n
  因此我们可以通过不断将 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值