leetCode第172题——阶乘后的零

Posted 小志的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetCode第172题——阶乘后的零相关的知识,希望对你有一定的参考价值。

一、题目

给定一个整数 n ,返回 n! 结果中尾随零的数量。提示:0 <= n <= 10的4次幂
进阶:你可以设计并实现对数时间复杂度的算法来解决此问题吗?

示例 1:
输入:n = 3
输出:0
解释:3! = 6 ,不含尾随 0

示例 2:
输入:n = 5
输出:1
解释:5! = 120 ,有一个尾随 0

示例 3:
输入:n = 0
输出:0

二、题目代码解析(迭代法实现)

1、代码

public class Test1 {
    public static void main(String[] args) {
        int a=trailingZeroes(50);
        System.out.println("阶乘后末尾为零的数量:【"+a+"】");
    }

    /**
     * 迭代计算阶乘
     */
    public static int trailingZeroes(int n){
        //迭代方式计算阶乘
        BigInteger nFactorial = BigInteger.ONE;
        for (int i = 2; i <= n; i++) {
            nFactorial = nFactorial.multiply(BigInteger.valueOf(i));
        }
        System.out.println("阶乘后的结果为:"+nFactorial);
        //如果一个数字末尾有零,那么它可以被 10整除。除以 10将删除该零,并将所有其他数字右移一位。
        //因此,我们可以通过反复检查数字是否可以被 1整除来计算末尾 0 的个数。
        int zeroCount = 0;//阶乘后的结果中尾随零的数量初始值0
        //阶乘后的数模10,取余数和0比较
        while (nFactorial.mod(BigInteger.TEN).equals(BigInteger.ZERO)) {
            //如果阶乘后的数模10取余数和0相等,把阶乘后的数除10
            nFactorial = nFactorial.divide(BigInteger.TEN);
            zeroCount++;//阶乘后的结果中尾随零的数量+1
        }
        return zeroCount;
    }

}

2、结果如下图:

三、进阶(计算因子方式实现)

思路摘自此博文链接https://leetcode.wang/leetcode-172-Factorial-Trailing-Zeroes.html
1、思路

  • 首先末尾有多少个 0 ,只需要给当前数乘以一个 10 就可以加一个 0。
  • 再具体对于 5!,也就是 5 * 4 * 3 * 2 * 1 = 120,我们发现结果会有一个 0,原因就是 2 和 5 相乘构成了一个 10。而对于 10 的话,其实也只有 2 * 5 可以构成,所以我们只需要找有多少对 2/5。
  • 我们把每个乘数再稍微分解下,看一个例子。
  • 11! = 11 * 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 11 * (2 * 5) * 9 * (4 * 2) * 7 * (3 * 2) * (1 * 5) * (2 * 2) * 3 * (1 * 2) * 1
  • 对于含有 2 的因子的话是 1 * 2, 2 * 2, 3 * 2, 4 * 2 …
  • 对于含有 5 的因子的话是 1 * 5, 2 * 5…
  • 含有 2 的因子每两个出现一次,含有 5 的因子每 5 个出现一次,所有 2 出现的个数远远多于 5,换言之找到一个 5,一定能找到一个 2 与之配对。所以我们只需要找有多少个 5。
  • 直接的,我们只需要判断每个累乘的数有多少个 5 的因子即可。

2、思路进阶

  • 对于一个数的阶乘,就如之前分析的,5 的因子一定是每隔 5 个数出现一次,也就是下边的样子。
  • n! = 1 * 2 * 3 * 4 * (1 * 5) * … * (2 * 5) * … * (3 * 5) *… * n
  • 因为每隔 5 个数出现一个 5,所以计算出现了多少个 5,我们只需要用 n/5 就可以算出来。但还没有结束,继续分析。
  • … * (1 * 5) * … * (1 * 5 * 5) * … * (2 * 5 * 5) * … * (3 * 5 * 5) * … * n
  • 每隔 25 个数字,出现的是两个 5,所以除了每隔 5 个数算作一个 5,每隔 25 个数,还需要多算一个 5。
  • 也就是我们需要再加上 n / 25 个 5
  • 同理我们还会发现每隔 5 * 5 * 5 = 125 个数字,会出现 3 个 5,所以我们还需要再加上 n / 125 。
  • 综上,规律就是每隔 5 个数,出现一个 5,每隔 25 个数,出现 2 个 5,每隔 125 个数,出现 3 个 5… 以此类推。
  • 最终 5 的个数就是 n / 5 + n / 25 + n / 125 …
  • 写程序的话,如果直接按照上边的式子计算,分母可能会造成溢出。所以算 n / 25 的时候,我们先把 n 更新,n = n / 5,然后再计算 n / 5 即可。后边的同理。

3、代码

public class Test1 {
    public static void main(String[] args) {
        //int a=trailingZeroes(50);
        int a=trailingZeroe(50);
        System.out.println("阶乘后末尾为零的数量:【"+a+"】");
    }
    public static int trailingZeroe(int n) {
        int count = 0;
        while (n > 0) {
            count += n / 5;
            n = n / 5;
        }
        return count;
    }
}

4、结果如下图:

以上是关于leetCode第172题——阶乘后的零的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 172 阶乘后的零[数学] HERODING的LeetCode之路

LeetCode 172. 阶乘后的零 / 682. 棒球比赛 / 2028. 找出缺失的观测数据

LeetCode 172. 阶乘后的零(Factorial Trailing Zeroes)

LeetCode.172- 阶乘后的零

LeetCode172. 阶乘后的零

LeetCode 172. 阶乘后的零