Loading

Easy | LeetCode 172. 阶乘后的零 | 数学

172. 阶乘后的零

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

示例 1:

输入: 3
输出: 0
解释: 3! = 6, 尾数中没有零。

示例 2:

输入: 5
输出: 1
解释: 5! = 120, 尾数中有 1 个零.

说明: 你算法的时间复杂度应为 O(log n) 。

解题思路

方法一: 暴力算法

直接求结果, 然后数出结果有多少个0。

public int trailingZeroes(int n) {
    int factorial = 1;
    for (int i = 1; i <= n; i++) {
        factorial *= i;
    }
    return zeroesCount(factorial);
}

public int zeroesCount(int x) {
    int zeroCount = 0;
    while (x % 10 == 0) {
        zeroCount++;
        x /= 10;
    }
    return zeroCount;
}

方法二: 暴力找因子5出现的次数

首先要知道一点, 某个数里尾数0是如果来的。10, 40, 100, 120等等。尾数的0, 一定是由他的因子2和因子5相乘得到。

所以问题转化为1, 2, 3 ... N这N个数字里, 因子2出现了多少次, 因子5出现了多少次。取这两个次数的较小者就是尾数0的个数。

再思考的话, 又可以发现个一个规律。因子2出现次数和因子5出现次数的较小者一定是因子5出现的次数。因为在1,2,3 ... N这N个数字里, 因子2, 每2个数字就会出现, 而因子5, 每5个数字才会出现。所以因子2的个数, 远大于因子5的个数。所以最终的问题转化为求因子5出现的个数。

public int trailingZeroes(int n) {
    int count = 0;
    // 遍历1,2,3...N
    for (int i = 1; i <= n; i++) {
        int N = i;
        // 找当前数字i, 因子5出现的次数
        while (N > 0) {
            if (N % 5 == 0) {
                count++;
                N /= 5;
            } else {
                break;
            }
        }
    }
    return count;
}

方法三: 找因子5出现次数

比方法二还有一个更好的方法去求5出现的次数。

方法二说到了5是每5个出现一次, 在[1...N]上, 会出现5的数字是5, 10, 15, 20, 25, 30, 35, 40, 45, 50 ...... 250, 255....等。在这一轮计算里, 出现了数字有n / 5个。

这样是不够的, 这其中还有25, 50, 100....。这些数字5因子都是出现了2次的。所以这些数字还要再加上一次。也就是n / 25次。

与上面同样的道理, 这里还有125, 250, 375, 500..., 这些因子里数字5因子是出现了3次的。所以这些数字还要再加上一次, 也就是n / 125次。

所以实际结果就是n/5 + n/25 + n/125 + n/625 + .....

public int trailingZeroes(int n) {
    int count = 0;
    while (n > 0) {
        count += n / 5;
        n = n / 5;
    }
    return count;
}
posted @ 2021-04-05 20:17  反身而诚、  阅读(46)  评论(0编辑  收藏  举报