力扣每日一题0325-172. 阶乘后的零

210 阅读3分钟

“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”

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

数学

n!n!n! 尾零的数量即为 n! 中因子 10 的个数,而 10=2×5,因此转换成求 n! 中质因子 2 的个数和质因子 5 的个数的较小值。

由于质因子 5 的个数不会大于质因子 2 的个数(具体证明见方法二),我们可以仅考虑质因子 5 的个数。

而 n! 中质因子 5 的个数等于 [1,n] 的每个数的质因子 5 的个数之和,我们可以通过遍历 [1,n] 的所有 5 的倍数求出。

var trailingZeroes = function(n) {
    let ans = 0;
    for (let i = 5; i <= n; i += 5) {
        for (let x = i; x % 5 == 0; x /= 5) {
            ++ans;
        }
    }
    return ans;
};

复杂度分析

  • 时间复杂度:O(n)。n! 中因子 5 的个数为 O(n),具体证明见方法二。

  • 空间复杂度O(1)。

优化计算

  • 肯定不可能真去把 n! 的结果算出来,阶乘增长可是比指数增长都恐怖
  • 两个数相乘结果末尾有 0,一定是因为两个数中有因子 2 和 5,因为 10 = 2 x 5
  • 也就是说,问题转化为:n! 最多可以分解出多少个因子 2 和 5
  • 举例来说,n = 25,那么 25! 最多可以分解出几个 2 和 5 相乘?这个主要取决于能分解出几个因子 5,因为每个偶数都能分解出因子 2,因子 2 肯定比因子 5 多得多
  • 现在,问题转化为:n! 最多可以分解出多少个因子 5
  • 假设 n = 125,来算一算 125! 的结果末尾有几个 0
  • 125 / 5 = 25,这一步就是计算有多少个像 5,15,20,25 这些 5 的倍数,它们一共可以提供一个因子 5
  • 像 25,50,75 这些 25 的倍数,可以提供两个因子 5,那么我们再计算出 125! 中有 125 / 25 = 5 个 25 的倍数,它们每人可以额外再提供一个因子 5
  • 我们发现 125 = 5 x 5 x 5,像 125,250 这些 125 的倍数,可以提供 3 个因子 5,那么我们还得再计算出 125! 中有 125 / 125 = 1 个 125 的倍数,它还可以额外再提供一个因子 5
  • 125! 最多可以分解出 25 + 5 + 1 = 31 个因子 5,也就是说阶乘结果的末尾有 31 个 0
/**
 * @param {number} n
 * @return {number}
 */
var trailingZeroes = function (n) {
  let res = 0;
  let divisor = 5;
  while (divisor <= n) {
    res += Math.floor(n / divisor);
    divisor *= 5;
  }
  return res;
};