【每天学习一点算法 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)

相关推荐
Frostnova丶21 小时前
【算法笔记】数学知识
笔记·算法
xqqxqxxq21 小时前
哈希表(HashMap)技术学习笔记
笔记·学习·散列表
生而为虫21 小时前
[学习记录] 幼儿学习拼音html游戏
学习·游戏
吴可可12321 小时前
AutoCAD 2016与2014二次开发关键差异
算法
AOwhisky21 小时前
MySQL 学习笔记(第四期):SQL 语言之多表查询
linux·运维·网络·数据库·笔记·学习·mysql
xian_wwq1 天前
【学习笔记】「大模型安全:攻击面演化史」第 07 篇-安全左移
人工智能·笔记·学习
秋雨梧桐叶落莳1 天前
iOS——NSUserDefaults学习
学习·macos·ios·objective-c·cocoa
雨白1 天前
哈希:以时间换空间的算法实战
算法
易小染1 天前
AI-Agent学习-LangChain-01
学习·langchain