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

求1-20最小公倍数的递归函数为何触发调用栈溢出?

解决递归栈溢出问题:找出1-20所有数的最小公倍数

你说得没错,这个栈溢出错误确实是因为递归没有正确触发终止条件,而且你的代码里还有几个关键逻辑错误,我们一步步拆解:

1. 核心问题:num++导致无限递归

你写的return findSmallest(num++)里,后置递增运算符num++会先返回当前的num值,再对num进行加1操作。这意味着每次递归调用传递的参数都是原来的num,而不是num+1!比如第一次调用findSmallest(20)时,发现不满足条件,会调用findSmallest(20)(而不是21),这样就陷入了无限递归,永远触发不了终止条件,最终耗尽调用栈。

要解决这个问题,你需要改成findSmallest(num + 1)或者findSmallest(++num)(前置递增,先加1再返回值)。

2. 第二个逻辑错误:漏掉了对数字2的检查

你的count初始值是2,进入while(count < 21)后第一行就是count++,这意味着第一次循环检查的是count=3,完全跳过了检查num是否能被2整除!这会导致很多不符合条件的数被错误地认为满足Condition D,进一步增加递归次数,甚至可能返回错误的结果。

应该把count++放在循环的末尾,或者调整初始值和循环逻辑:

// 修正后的循环逻辑
var count = 2;
while (count <= 20) { // 改成<=20,避免最后漏掉20
  if (num % count !== 0) {
    return findSmallest(num + 1);
  }
  count++; // 检查完当前count再递增
}

3. 递归不是这个问题的最优解

即使修复了上面两个问题,你还是会遇到栈溢出。因为能被1-20所有数整除的最小数是232792560,从20开始递归的话需要调用函数超过2亿次,远远超出了JavaScript调用栈的最大深度(通常只有几千到几万层)。

更高效的做法是用迭代法计算最小公倍数(LCM),或者利用数学原理:多个数的最小公倍数等于它们的质因数的最高次幂的乘积。

推荐的迭代解法(计算LCM)

首先,我们需要一个计算两个数最大公约数(GCD)的函数,然后利用公式LCM(a,b) = (a*b)/GCD(a,b),逐步计算1到20的LCM:

// 欧几里得算法计算最大公约数
function gcd(a, b) {
  while (b !== 0) {
    let temp = b;
    b = a % b;
    a = temp;
  }
  return a;
}

// 计算两个数的最小公倍数
function lcm(a, b) {
  return (a * b) / gcd(a, b);
}

// 计算1到n的最小公倍数
function findSmallestMultiple(n) {
  let result = 1;
  for (let i = 2; i <= n; i++) {
    result = lcm(result, i);
  }
  return result;
}

console.log(findSmallestMultiple(20)); // 输出232792560

这个方法只需要循环19次,效率极高,完全不会有栈溢出的问题。

总结一下你的代码问题:

  • num++的误用导致无限递归,这是栈溢出的直接原因
  • 循环中count的递增顺序错误,漏掉了对数字2的检查
  • 递归方式不适用于这个需要大量迭代的问题

内容的提问来源于stack exchange,提问作者David J.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:26:24