算法-阶乘函数后 K 个零

124 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

题目

leetcode 793. 阶乘函数后 K 个零

f(x) 是 x! 末尾是 0 的数量。回想一下 x! = 1 * 2 * 3 * ... * x,且 0! = 1 。

例如, f(3) = 0 ,因为 3! = 6 的末尾没有 0 ;而 f(11) = 2 ,因为 11!= 39916800 末端有 2 个 0 。 给定 k,找出返回能满足 f(x) = k 的非负整数 x 的数量。

 

示例 1:

输入:k = 0
输出:5
解释:0!, 1!, 2!, 3!, 和 4! 均符合 k = 0 的条件。

示例 2:

输入:k = 5
输出:0
解释:没有匹配到这样的 x!,符合 k = 5 的条件。

示例 3:

输入: k = 3
输出: 5

提示:

0 <= k <= 109

题解

首先想到的是,阶乘末尾0的个数完全由5的因子个数决定,因为2的个数由于多于5的个数,所以讨论5即可。

其次想到的是计算一个数有多少个5的因子,需要依次除以5的各个次方,每个次方会单独贡献一个额外的5。

上面的式子和差比求和公式是一致的,不过这里是整除,但是我们仍可得到这个数字的范围。(原式乘以5再作差,会得到该数字一定大于等于4 * k)5的因子个数是随着数字变大单调不减的。

有k个5的因子的数上界也很容易确定,比较宽松的估一个5 * (k + 1)即可 (兼容k=0的情况)。

在已知的上下界里二分校验有没有数有k个5的因子即可,如果没有返回0,如果有说明该数x (x % 5 == 0)到 x + 4 这五个数都满足。

var preimageSizeFZF = function(k) {
    return help(k + 1) - help(k);
}

const help = (k) => {
    let r = 5 * k;
    let l = 0;
    while (l <= r) {
        const mid = Math.floor((l + r) / 2);
        if (zeta(mid) < k) {
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    return r + 1;
}

const zeta = (x) => {
    let res = 0;
    while (x != 0) {
        res += Math.floor(x / 5);
        x = Math.floor(x / 5);
    }
    return res;
};