LeetCode 202. 快乐数:快慢指针解法详解
在数学的世界里,有些数字被赋予了特殊的含义。快乐数(Happy Number)就是其中之一。简单来说,如果一个正整数经过'各位数字平方和'的反复替换后最终得到 1,它就是快乐数;如果陷入不包含 1 的循环,就是不快乐的。
以 19 为例,过程如下: 19 → 1² + 9² = 82 82 → 8² + 2² = 68 68 → 6² + 8² = 100 100 → 1² + 0² + 0² = 1
经过 4 步变换,19 到达了终点。
核心思路:链表判环
虽然处理的是数字,但我们可以把每个数字看作链表中的一个节点,变换规则看作指向下一个节点的指针。这样,快乐数问题就转化为了经典的链表判环问题。
对于不快乐的数字,序列会进入一个闭环。例如:4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4。一旦检测到环,即可判定为非快乐数。
算法实现:快慢指针
解决链表判环最优雅的方法是使用快慢指针(Floyd 判圈算法)。想象龟兔赛跑,两个指针从起点出发,速度不同:
- 慢指针(slow):每次变换一次数字。
- 快指针(fast):每次变换两次数字。
如果存在环,快指针终将追上慢指针;如果数字是快乐的,快指针会先到达 1。
辅助函数:数字变换
我们需要一个函数来计算下一个数字。逻辑很简单:取余获取末位,平方累加,整除去掉末位。
int getNext(int n) {
int sum = 0;
while (n > 0) {
int digit = n % 10; // 获取最后一位数字
sum += digit * digit;
n /= 10; // 去掉最后一位数字
}
return sum;
}
主逻辑判断
有了辅助函数,主逻辑就清晰了。注意初始化时快指针要先走一步,避免初始状态相同导致误判。
bool isHappy(int n) {
int slow = n; // 慢指针
int fast = getNext(n); // 快指针先走一步
// 当快指针未到 1 且快慢指针未相遇时继续
while (fast != 1 && slow != fast) {
slow = getNext(slow); // 慢指针走一步
fast = ((fast));
}
fast == ;
}


