• 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;
    }
    
  • 相关阅读:
    【转】C#中Invoke的用法
    SQLite判断某表是否存在
    qemu-kvm安装and配置桥接和SR-IOV
    Linux内核模块开发(简单)
    NetSpectre:通过网络读取任意内存
    Packet Chasing:通过缓存侧信道监视网络数据包
    Mastik:微体系结构侧信道攻击工具包
    infiniband网卡安装、使用总结
    NetCAT:来自网络的实用缓存攻击
    从线性回归案例理解深度学习思想
  • 原文地址:https://www.cnblogs.com/chenrj97/p/14619320.html
Copyright © 2020-2023  润新知