You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归求阶乘引发栈溢出的原因解析及LeetCode #172题代码报错排查

关于LeetCode #172 阶乘末尾零计数的问题分析与解决

为什么递归求阶乘会栈溢出?

当你用递归计算findFactorial(n)时,每一次递归调用都会在调用栈中创建一个新的栈帧——这个栈帧会保存当前函数的局部变量、返回地址等信息。Java的默认调用栈深度是有限的(通常在几千级别,比如默认可能是1024或2048),而当n达到104时,递归深度会达到104层,远远超过了栈的承载能力,所以就会抛出StackOverflowError。

举个例子:调用findFactorial(10000)会触发findFactorial(9999),接着是findFactorial(9998)……直到findFactorial(1),这中间有9999次连续的递归调用,栈根本装不下这么多栈帧,自然就溢出了。

你的解法还有另一个致命问题:数值溢出

除了栈溢出,你的代码还存在整数溢出的问题:Java中int类型的最大值是2^31-1(约21亿),而13!的结果是6227020800,已经超过了int的范围。当n≥13时,findFactorial(n)计算出的结果会是错误的溢出值,后续统计末尾零的逻辑自然也得不到正确结果。

正确的解题思路:统计因子5的个数

其实求n!末尾零的个数,不需要计算完整的阶乘结果——我们只需要统计1到n中所有数包含的因子5的总个数。原因很简单:末尾的零来自于10的倍数,而10=2×5,在阶乘中因子2的数量远多于因子5,所以有多少个5的因子,就有多少个末尾零。

需要注意的是,像25(5×5)、125(5×5×5)这类数,会贡献多个5的因子,所以我们需要循环计算:

  • 先统计n中能被5整除的数的个数:n/5
  • 再统计能被25整除的数的个数(每个贡献第二个5):n/25
  • 接着统计能被125整除的数的个数:n/125
  • 以此类推,直到除数大于n为止

修正后的代码

class Solution {
    public int trailingZeroes(int n) {
        int count = 0;
        // 循环统计所有5的幂次的因子个数
        while (n > 0) {
            n = n / 5;
            count += n;
        }
        return count;
    }
}

这个解法不仅避免了栈溢出和数值溢出,时间复杂度还只有O(log₅n),效率极高,完全能处理n=10^4的情况。

内容的提问来源于stack exchange,提问作者SomeoneLearning17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:48:21