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

相关推荐
w_zero_one1 小时前
递归算法(一)
java·开发语言·算法
风影同志783243 小时前
20 个比特能装下多少行情?——实测拆解 Kronos 的 K 线分词器
算法
写的都是BUG4 小时前
APK 里的钥匙,一直就放在门口:聊聊加固真正该做什么
前端·算法
La Pulga4 小时前
【FreeRTOS源码学习笔记】空闲任务与阻塞延时
笔记·mcu·学习·嵌入式·freertos·实时操作系统
蒸蒸yyyyzwd4 小时前
秋招学习笔记 day106
笔记·学习
地平线开发者4 小时前
CLIP 的零样本分类:一组文本如何变成图像分类器?
算法
京东云开发者5 小时前
从“会生成”到“能生产”:萤火虫 AIGC 平台的 AI Infra 实践
算法·aigc·产品
youshi66685 小时前
PID——算法改进
算法
小李不想当小白5 小时前
WDG看门狗(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
一只不想敲代码的程序猿6 小时前
如何更高效地拆解问题?
算法