1. 问题背景与核心挑战
这道LeetCode 793题看似简单,实则暗藏玄机。题目要求我们找到所有满足阶乘结果末尾恰好有K个零的非负整数n的个数。换句话说,给定K,我们需要统计有多少个n满足trailingZeroes(n!) == K。
阶乘末尾零的个数问题本身就是一个经典面试题。我们都知道,末尾零的数量取决于因子5的个数(因为2的因子总是比5多)。计算单个n!的末尾零数可以通过累加n/5 + n/25 + n/125...来实现。但本题将这个经典问题提升到了一个新的难度层级——我们需要反向思考,给定零的个数K,找出所有对应的n。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路拆解
2.1 数学基础:阶乘末尾零的计算原理
首先我们需要彻底理解阶乘末尾零的计算方式。每个末尾零对应一个10的因子,而10=2×5。在阶乘中,2的因子总是比5多,因此零的个数完全由5的因子数量决定。
计算n!中5的因子数量的公式为:
z(n) = ⌊n/5⌋ + ⌊n/25⌋ + ⌊n/125⌋ + ...
这个级数会一直加到⌊n/5^k⌋为零为止。例如:
- z(5) = 1
- z(10) = 2
- z(25) = 6 (25/5 + 25/25 = 5+1=6)
2.2 关键观察:z(n)函数的单调性
z(n)函数有一个重要性质——它是单调不减的。这意味着随着n的增加,z(n)要么保持不变,要么增加。这个性质对我们的解题至关重要,因为它允许我们使用二分查找来高效地解决问题。
当n增加1时,z(n)的变化取决于这个数包含多少个5的因子。例如:
- z(4)=0, z(5)=1(增加了1)
- z(24)=4, z(25)=6(增加了2,因为25是5^2)
2.3 问题转化:寻找z(n)=K的区间
由于z(n)是单调不减的,所有满足z(n)=K的n必然构成一个连续区间。我们的任务就转化为:
- 找到最小的n_min使得z(n_min)=K
- 找到最大的n_max使得z(n_max)=K
- 结果就是n_max - n_min + 1(如果存在这样的n),否则为0
3. 算法设计与实现
3.1 二分查找框架
基于上述观察,我们可以设计一个二分查找的解决方案:
python复制def preimageSizeFZF(K):
