快乐数是反复将各位数字平方和相加最终得1的正整数;非快乐数必落入4→16→37→58→89→145→42→20→4循环,故可用快慢指针o(1)空间检测环,无需暴力设上限或哈希表。

什么是快乐数,以及为什么不能用暴力循环
一个正整数反复将各位数字平方和相加,最终结果变为 1,就是快乐数;如果进入非 1 的循环(比如掉进 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 这个环),就不是快乐数。很多人第一反应是设个大上限(比如 1000 次)硬跑,但这样既不严谨(可能漏判),又慢——尤其在高频调用或嵌入式场景下。
关键点在于:所有非快乐数最终都会落入以 4 为起点的固定循环。数学上已证明,对任意正整数,其数字平方和不会超过 81 * digits(比如 999 → 3×81=243),因此状态空间极小(n ≤ 243 时,下一个值一定 ≤ 243)。这意味着必然出现重复,而重复点只有两类:要么是 1(成功),要么是环中某个非 1 值(失败)。
用快慢指针检测循环(O(1) 空间 + 无哈希表)
既然本质是找链表是否有环,floydCycleDetection 是最轻量的解法:只用两个整数变量,不申请额外容器,避免哈希表的内存开销与哈希冲突成本。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 定义函数
nextNum(int n):逐位取模、平方、累加,注意别写成n % 10 * n % 10(运算符优先级错误) - 初始化
slow = n,fast = nextNum(n) - 循环条件:
slow != fast && fast != 1;每次slow = nextNum(slow),fast = nextNum(nextNum(fast)) - 退出后只需检查
fast == 1即可——因为若环存在且不含1,fast必与slow相遇于环内某点,此时fast != 1
int nextNum(int n) {
int sum = 0;
while (n) {
int d = n % 10;
sum += d * d;
n /= 10;
}
return sum;
}
<p>bool isHappy(int n) {
int slow = n, fast = nextNum(n);
while (slow != fast && fast != 1) {
slow = nextNum(slow);
fast = nextNum(nextNum(fast));
}
return fast == 1;
}</p>
预计算小范围结果加速高频查询
如果程序中要判断大量正整数(如筛出 1~10000 内所有快乐数),每次都跑快慢指针仍有冗余。由于所有数最终都会收敛到 ≤ 243 的范围,可以预先打表 isHappyTable[244](索引 0~243),之后对任意 n,只需不断调用 nextNum 直到值 ≤ 243,再查表。
- 表大小选 244 而非 243:避免
nextNum(199) = 1²+9²+9² = 163,安全起见留点余量 - 初始化表时,对每个
i ∈ [1, 243],用快慢指针算一次并存布尔值,后续 O(1) 查 - 注意
nextNum(1) == 1,所以isHappyTable[1] = true;而isHappyTable[4]必为false - 实际使用中,先
while (n > 243) n = nextNum(n);,再返回isHappyTable[n]
容易被忽略的边界与性能陷阱
看似简单的问题,实操时几个点常导致 WA 或 TLE:
-
nextNum中对0的处理:输入不会为 0(题设是正整数),但中间值可能为 0(如10 → 1²+0² = 1),循环条件必须用while (n)而非while (n > 0)(等价,但更习惯前者) - 快慢指针初始偏移:必须让
fast先走一步(或两步),否则第一次就slow == fast,直接返回true——这是常见笔误 - 整型溢出风险:虽然
int足够(最大中间值如 999999999 → 9×81 = 729),但若扩展到 long long 输入,nextNum内部仍用int sum可能溢出,应改为long long sum - 编译器优化提示:
nextNum是纯函数,可加constexpr(C++14 起),让部分常量输入在编译期计算
真正卡性能的从来不是算法本身,而是没意识到所有轨迹都塌缩到极小状态空间——抓住这点,就不用纠结“会不会无限循环”,也不用背那个 4 开头的环。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










