来源:力扣(LeetCode)
描述:
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
提示:
方法:二分查找
思路与算法
首先我们令 zeta(x) 为 x! 末尾零的个数。根据 「172. 阶乘后的零」 的题解,有
记 nx 表示 x! 末尾零的个数 不小于 x 的最小数,那么题目等价于求解 nk+1 - nk。
由于 zeta(x) 为 单调不减函数,因此 nk+1 和 nk 可以通过「二分查找」来求解。
又因为
得
所以当二分求解 nk 时,我们可以将二分的初始右边界 r 设置为 5x。
代码:
class Solution {
public:
int zeta(long x) {
int res = 0;
while (x) {
res += x / 5;
x /= 5;
}
return res;
}
long long help(int k) {
long long r = 5LL * k;
long long l = 0;
while (l <= r) {
long long mid = (l + r) / 2;
if (zeta(mid) < k) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return r + 1;
}
int preimageSizeFZF(int k) {
return help(k + 1) - help(k);
}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.8 MB, 在所有 C++ 提交中击败了72.15%的用户
复杂度分析
时间复杂度:O(log2k),其中 k 为题目给定数字,二分查找 nk+1 和 nk 的时间复杂度为 O(logk),其中每一步计算 zeta(x) 的时间复杂度为 O(logk)。
空间复杂度: O(1), zeta(x) 仅为常量空间开销。
author:LeetCode-Solution