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

📅 小哆啦刷题 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) 进阶思维,链表判环思想迁移

🎓 总结一句话

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

相关推荐
码破苍穹ovo1 小时前
堆----1.数组中的第K个最大元素
java·数据结构·算法·排序算法
愤怒的小鸟~~~1 小时前
c语言创建的一个队列结构(含有这个头指针和这个尾指针的结构具有一定的参考价值)
c语言·开发语言·算法
Joker-01113 小时前
深入 Go 底层原理(十二):map 的实现与哈希冲突
算法·go·哈希算法·map
金融小师妹4 小时前
AI量化模型解析黄金3300关口博弈:市场聚焦“非农数据”的GRU-RNN混合架构推演
大数据·人工智能·算法
金融小师妹4 小时前
基于LSTM-GRU混合网络的动态解析:美联储维稳政策与黄金单日跌1.5%的非线性关联
大数据·人工智能·算法
白日梦想家-K4 小时前
题单【模拟与高精度】
开发语言·c++·算法
重生之我是Java开发战士5 小时前
【C语言】内存函数与数据在内存中的存储
c语言·开发语言·算法
roman_日积跬步-终至千里6 小时前
【机器学习】“回归“算法模型的三个评估指标:MAE(衡量预测准确性)、MSE(放大大误差)、R²(说明模型解释能力)
算法·机器学习·回归
小指纹7 小时前
图论-最短路Dijkstra算法
数据结构·c++·算法·深度优先·图论
赴3358 小时前
逻辑回归 银行贷款资格判断案列优化 交叉验证,调整阈值,下采样与过采样方法
算法·机器学习·逻辑回归·下采样·交叉验证·过采样·阈值