题解采用了二分查找的方法来确定具有k个末尾0的最小和最大的x值。首先,函数f(n)计算n的阶乘末尾0的数量,这是通过计算n可以被5的多少次幂整除来实现的。对于给定的k,通过使用两次二分查找,一次寻找满足f(x) = k的最小x值,另一次寻找最大x值。如果k不可能达到(如中间出现跳跃),这两个查找返回的区间会是空的,否则区间内每一个整数都满足条件。搜索范围设定在4k到5(k+1)之间是基于阶乘末尾0的数量增长的大致速度推导出的。
时间复杂度: O(log^2(n))
空间复杂度: O(1)
class Solution:
def preimageSizeFZF(self, k: int) -> int:
# 设置二分查找的初始左右界限
left = 4 * k
right = 5 * (k + 1)
# 第一次二分查找,找到f(x) >= k的最小x
while left <= right:
mid = left + (right - left) // 2
temp = self.f(mid)
if temp >= k:
right = mid - 1
else:
left = mid + 1
lo = left
# 重新设置左右界限
left = 4 * k
right = 5 * (k + 1)
# 第二次二分查找,找到f(x) <= k的最大x
while left <= right:
mid = left + (right - left) // 2
temp = self.f(mid)
if temp > k:
right = mid - 1
else:
left = mid + 1
hi = right
# 计算满足条件的x的数量
return int(hi - lo + 1)
def f(self, n: int) -> int:
# 计算n的阶乘的末尾0的数量
res = 0
while n:
n //= 5
res += n
return res