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

如何高效终止判断快乐数的递归函数,避免出现无限循环问题?

问题根源

你实现的是快乐数判断逻辑,非快乐数的各位平方和计算最终会进入固定循环(4→16→37→58→89→145→42→20→4),不会走到1的终止条件,因此会无限递归。另外你当前代码存在拼写bug:求和函数定义为sqaureSum,但递归函数中调用的是squareSum,需要先修正拼写。

优化方案

方案1:基于数学规律的极简终止条件(效率最高,无额外开销)

数学上已证明所有非快乐数的平方和运算最终都会落到4,你之前加的x === 4终止条件实际效率并不低——任意大的整数最多经过十几次平方和运算就会落到个位数,不存在效率问题。可以直接基于这个规则调整递归函数,自定义返回值适配后续计算:

function recursion(x) {
  // 自定义返回规则:是快乐数返回1,非快乐数返回0,可按需调整
  if (x === 1) return 1;
  if (x === 4) return 0;
  x = squareSum(x);
  return recursion(x);
}

方案2:递归加访问标记(通用循环检测方案,适配自定义规则)

如果后续需要调整逻辑,不想依赖固定终止值,可以给递归函数增加访问集合参数,检测到重复值就说明进入循环,直接返回结果:

function recursion(x, visited = new Set()) {
  if (x === 1) return 1;
  // 出现重复值说明进入循环,不是快乐数
  if (visited.has(x)) return 0;
  visited.add(x);
  x = squareSum(x);
  return recursion(x, visited);
}

方案3:快慢指针迭代实现(无递归栈溢出风险,空间复杂度O(1))

如果输入数值很大,递归可能触发调用栈溢出,推荐用Floyd快慢指针法迭代实现,不需要额外存储访问集合,也不会有栈溢出问题:

function isHappy(n) {
  function squareSum(num) {
    let sum = 0;
    while (num > 0) {
      const digit = num % 10;
      sum += digit * digit;
      num = Math.floor(num / 10);
    }
    return sum;
  }
  let slow = n;
  let fast = squareSum(n);
  while (fast !== 1 && slow !== fast) {
    slow = squareSum(slow);
    fast = squareSum(squareSum(fast));
  }
  return fast === 1 ? 1 : 0;
}

附属优化:平方和函数改迭代

你当前的squareSum本身也是递归实现,嵌套在快乐数递归逻辑中会增加栈溢出风险,改成迭代版本更稳定:

function squareSum(n){
    let sumTotal = 0;
    while(n > 0){
        sumTotal += Math.pow(n % 10, 2);
        n = Math.floor(n / 10);
    }
    return sumTotal;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:48:05