快乐数是指正整数经各位数字平方和迭代后最终得1;非快乐数必入4→16→37→58→89→145→42→20→4循环,故只需判n==1或n==4即可终止,无需计数或哈希表。

什么是快乐数,以及为什么不能只靠“循环次数”来判断
快乐数的定义是:对一个正整数不断替换为它各位数字的平方和,最终结果为 1,则它是快乐数;否则会陷入循环(比如进入 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 这个经典环)。很多人误以为只要迭代 100 次没到 1 就不是快乐数——这不可靠,因为不同起始值进入环的步数差异大,且没有理论上限。
真正可靠的极速判别法,是检测是否进入已知的「非快乐数循环」。数学上已证明:所有非快乐数最终都会落入以 4 为起点的 8 数循环(即上面那个序列),所以只需判断是否到达 4 即可提前终止。
- 一旦当前数变为
4,立刻返回false - 若变为
1,返回true - 其它数继续计算平方和,无需缓存历史值,空间 O(1)
如何高效计算各位数字的平方和(避免字符串转换)
用字符串转数字再遍历,性能差且引入额外内存分配。直接用整数模除法拆位,是 C++ 中最轻量的方式。
注意:0 的平方和是 0,但输入保证是正整数,所以初始值 ≥ 1;不过中间过程可能出现 0(如 10 → 1² + 0² = 1),逻辑上无问题。
- 用
while (n) { sum += (n % 10) * (n % 10); n /= 10; } - 不要用
to_string或stringstream,尤其在高频调用场景下明显拖慢 - 对
int类型,最大输入(如INT_MAX≈ 2e9)产生的平方和最大为9²×10 = 810,后续迭代数迅速收敛,不会溢出int
C++ 实现:带 early-return 的极简版本
以下代码不依赖哈希表,不记录路径,仅用两个状态判断(1 和 4),时间复杂度最坏也是常数级(因数值快速坍缩至百以内,且最多约 20 步就命中 1 或 4)。
bool isHappy(int n) {
while (n != 1 && n != 4) {
int sum = 0;
while (n) {
int d = n % 10;
sum += d * d;
n /= 10;
}
n = sum;
}
return n == 1;
}
这个写法比用 unordered_set 记录访问过的数快 3–5 倍(实测 LeetCode 数据),且零内存分配。唯一要注意的是:必须严格检查 n == 4,不能只写 n == 1 后加 else,否则会无限循环。
容易被忽略的边界与测试点
有人用 19 测试发现正确,就以为没问题——但漏掉了几个典型坑:
-
1是快乐数,函数必须立刻返回true(上面 while 循环条件已覆盖) -
10→1²+0²=1,应为true;2→4→ … →4,应为false - 如果把判断写成
if (n == 1) return true; else if (n == 4) return false;,但没更新n就跳出循环,会导致逻辑错误 - 不要在循环内对
n做自增/自减操作,否则破坏模除逻辑
真正关键的不是“怎么算平方和”,而是“什么时候停”。盯住 1 和 4 这两个锚点,其它都是干扰项。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











