【每天学习一点算法 2026/04/07】快乐数

每天学习一点算法 2026/04/07

题目:快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。

然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。

如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

首先我们要明确,对一个数反复计算各位数字的平方和只有存在两个情况:

  1. 收敛到 1
  2. 进入一个固定的循环

假设是一个 m 位的数 ,每一位最大数只能是 9

那最大的计算结果就是 9 * 9 * m = 81m

然而这个数至少是 10m - 1 次方,当 m > 3 时,这个数本身是远远大于它每个位置上的数字的平方和的

所以我们知道一直重复计算一定不是发散的,一旦有了边界那么出现的数就是有限的,所以一直计算一定会进入循环 或者 收敛到 1(1 计算完还是 1 其实也是一种循环)。

于是我们只需要不断的计算直到遇到重复的数 或者 1

typescript 复制代码
function isHappy(n: number): boolean {
  const set = new Set()
  function helper(num: number) {
    if (set.has(num)) {
      return false
    }
    if (num === 1) {
      return true
    }
    set.add(num)
    const next = num.toString().split('').reduce((prev: number, current: string) => {
      return prev + Number(current) * Number(current)
    }, 0)
    return helper(next)
  }

  return helper(n)
};

既然是判断是否循环,其实我们还可以想到快慢指针的方法(龟兔赛跑),快指针每次计算两次,如果是快乐数快指针一定会先计算到 1,如果不是快乐数两个指针一定会相遇。

typescript 复制代码
function isHappy(n: number): boolean {
  function helper(n: number) {
    let totalSum = 0
    while (n > 0) {
      let d = n % 10
      n = Math.floor(n / 10)
      totalSum += d * d
    }
    return totalSum
  }
  let fast = n, slow = n
  fast = helper(fast)
  while (fast != slow && fast != 1) {
    // 快指针每次计算两次
    fast = helper(fast)
    fast = helper(fast)
    slow = helper(slow)
  }

  return fast === 1
};

题目来源:力扣(LeetCode)

相关推荐
To_OC11 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
旖-旎13 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
To_OC13 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
世人万千丶14 小时前
参数管理_Flutter在鸿蒙平台路由参数最佳实践
学习·flutter·华为·harmonyos·鸿蒙
delishcomcn14 小时前
AI视觉识别+分切算法:电化铝缺陷检测与裁切一体化解锁
人工智能·算法
触底反弹14 小时前
深入理解大模型采样:Temperature、Top-K、Top-P 的原理与实战
人工智能·算法·面试
雪碧聊技术14 小时前
力扣 LCR 091. 粉刷房子 —— 动态规划入门详解
算法·动态规划
遇乐的果园17 小时前
前端学习笔记-vue加载渲染优化
前端·笔记·学习
CV-Climber17 小时前
检索技术的实际应用
人工智能·算法