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

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

题目:快乐数

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

「快乐数」 定义为:

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

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

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

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

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

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

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

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

然而这个数至少是 10 的 m - 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)

相关推荐
leobertlan9 小时前
痛苦系列 | DSP-03 跨越单位圆:Z变换与零极点分析
算法·程序员
蛋蛋的就会顺顺的9 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
开发小能手1239 小时前
答案daanC语言
数据结构·算法
遇印记10 小时前
传输层,网络层
运维·服务器·网络·windows·学习
Navigator_Z11 小时前
LeetCode //C - 1291. Sequential Digits
c语言·算法·leetcode
clorinda11 小时前
PyQt5学习:从界面搭建到与机器学习实战
学习
pride.li12 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
欣欣之王来了13 小时前
Vue3项目脚手架:Vite vs Vue CLI怎么选?
前端·学习·架构·项目·vue3教程
旺仔仔仔13 小时前
机器人项目实战(5):从单次抓取,到接收指令连续做事
算法
kaixin_啊啊13 小时前
【零基础学AI】第 7 章——让 AI 辅助学习和办公
人工智能·学习