双指针算法实战:快乐数与盛水最多容器
03. 快乐数
题目描述: 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果这个过程结果为 1,那么这个数就是快乐数。
思路拆解: 为了方便叙述,我们将「计算各位数字平方和」这一操作记为 x。不断重复 x 操作时,结果只有两种走向:要么收敛到 1,要么陷入死循环。
这里有个关键观察:经过多次变换后,数值范围其实很小(最大不会超过 9^2 * 10 = 810)。根据鸽巢原理,变化过程必然会在有限步内形成循环。既然存在环,我们就可以用「快慢指针」来检测。
核心逻辑:
- 快指针每次走两步,慢指针每次走一步。
- 如果最终相遇在 1,说明是快乐数。
- 如果相遇在其他位置,说明陷入了非 1 的循环,不是快乐数。
辅助函数实现: 我们需要一个函数来计算 n 的各位数字平方和。逻辑很简单:取模提取个位,累加平方,整除去掉个位,循环直到 n 为 0。
class Solution {
public:
// 计算各位数字的平方和
int bitsum(int n) {
int sum = 0;
while (n) {
int t = n % 10;
sum += t * t;
n /= 10;
}
return sum;
}
bool isHappy(int n) {
int slow = n;
int fast = bitsum(n);
// 快慢指针寻找循环点
while (slow != fast) {
slow = bitsum(slow); // 慢指针走一步
fast = bitsum(bitsum(fast)); // 快指针走两步
}
return slow == 1; // 判断相遇点是否为 1
}
};


