🧠 小哆啦解题记 —— 谁偷走了我的快乐?

📅 小哆啦刷题 Day 37

题号:202. 快乐数 - 力扣(LeetCode)

关键词:数位平方和、哈希判环、数学循环论证、无限循环解释


第一章:大雄的灵魂发问

"哆啦A梦,最近怎么也开心不起来......难道我......不是个快乐数?"

大雄满脸迷茫地趴在课桌上。

哆啦A梦吃着铜锣烧冷静回答:"来,我带你刷一道题,看看你到底'快乐不快乐'。"


第二章:题目来了

给你一个正整数 n,重复如下操作:

  • 将其每一位数字的平方求和,得出新数。
  • 不断重复此过程。

如果最终可以变成 1,就是快乐数

如果陷入无限循环 却始终得不到 1,那就很遗憾,它不是快乐数


第三章:大雄的第一版代码(带点 Bug)

typescript 复制代码
function isHappy(n: number): boolean {
    let numMap: Map<number, number> = new Map();
    while (true) {
        let str = n.toString();
        n = str.split("").reduce((acc, cur) => acc + Math.pow(Number(cur), 2), 0);
        if (n == 1) return true;
        if (numMap.has(n)) return false;
        numMap.set(Number(str), n);
    }
}

"我每出现一个数就记录一下,如果又出现了,说明在无限转圈。"大雄自信地说。

哆啦A梦一边擦眼镜一边点头:"嗯......基本思路对,但你这 Map 存得太复杂,Set 更合适。"


第四章:哆啦A梦的快乐优化器

于是他甩出优化后的版本:

ini 复制代码
function isHappy(n: number): boolean {
    const seen = new Set<number>();
    while (n !== 1) {
        if (seen.has(n)) return false;
        seen.add(n);
        n = getNext(n);
    }
    return true;
}

function getNext(num: number): number {
    let sum = 0;
    while (num > 0) {
        const digit = num % 10;
        sum += digit * digit;
        num = Math.floor(num / 10);
    }
    return sum;
}

"每次记录出现过的数,只要你再走进来一次,就说明------你在绕圈。"


第五章:大雄困惑了:为什么就一定会循环?

"等等等等......你说 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 是循环,那为啥一定会循环?为啥不能一直变大,或者跑到 1e10?"

哆啦A梦收起铜锣烧,郑重地回答:


🧠 第六章:无限循环的数学机制,正式揭晓

🧩 一、每一步"变换"都有上限!

你以为这些数字会无限增长?错!

👉 最大增长速率远小于原数值本身。

比如一个 4 位数 9999,变换后是:

ini 复制代码
9² + 9² + 9² + 9² = 81 × 4 = 324

✨ 所以,不管你是 999999999 还是 9999,最终都收敛到一个相对较小的数。

实验证明:任意正整数,变换后最终都会收敛到 ≤ 243。

所以你最多只会经历 243 个不同状态,一旦遇到重复,就铁定进入循环!


🌀 二、经典环:不快乐循环的"死亡八卦阵"

试试 n = 2,看它怎么绕回自己:

erlang 复制代码
2 → 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 ...

恭喜,它回到 4 了,这就是经典的"非快乐数死循环"


第七章:进阶姿势·快慢指针

如果你不想用额外空间,那就用链表判环那一套------快慢指针

ini 复制代码
function isHappy(n: number): boolean {
    let slow = n, fast = getNext(n);
    while (fast !== 1 && slow !== fast) {
        slow = getNext(slow);
        fast = getNext(getNext(fast));
    }
    return fast === 1;
}

就像两只赛跑的仓鼠,一快一慢在圆环里转,如果能碰头,就说明陷入循环了。


第八章:终章·算法与人生的哲学

静香眨了眨眼:"那你们说,人类的快乐,是不是也能像这样判定?"

哆啦A梦认真回答:"如果你重复做一些事,却永远得不到满足,可能你已经掉进了非快乐循环。"


✅ 小哆啦的技术小结

解法 判环方式 时间复杂度 空间复杂度 特点
哈希表判环 Set 记录状态 O(logN) O(logN) 简单直观,好调试
快慢指针 空间优化 O(logN) O(1) 进阶思维,链表判环思想迁移

🎓 总结一句话

不是每一个数都有快乐结局,但每一个循环都有逃出生天的可能。

相关推荐
myw07120516 小时前
Leetcode94.二叉数的中序遍历练习
c语言·数据结构·笔记·算法
songx_9916 小时前
leetcode(填充每个节点的下一个右侧节点指针 II)
java·数据结构·算法·leetcode
chenyuhao202416 小时前
vector深度求索(上)实用篇
开发语言·数据结构·c++·后端·算法·类和对象
minstbe17 小时前
半导体数据分析:GPR算法小白入门(三) 晶体管I-V特性仿真教程
算法
未知陨落18 小时前
LeetCode:60.单词搜索
算法·leetcode
mmz120718 小时前
动态规划 练习(c++)
c++·算法·动态规划
tqs_1234518 小时前
分sheet写入excel
开发语言·python·算法
西望云天19 小时前
基础组合计数(三道例题)
数据结构·算法·icpc
小灰灰的FPGA20 小时前
29.9元汉堡项目:基于matlab+FPGA的FFT寻峰算法实现
算法·matlab·fpga开发
花心蝴蝶.21 小时前
JVM 垃圾回收
java·jvm·算法