快乐数
题目链接:
题目描述:
给定一个正整数 n,每一次将该数替换为它每个位置上的数字的平方和。返回如果该过程最终结果为 1 则是快乐数,否则不是。
题目示例:
输入:n = 19 输出:true 解释:1^2 + 9^2 = 82 -> 8^2 + 2^2 = 68 -> 6^2 + 8^2 = 100 -> 1^2 + 0^2 + 0^2 = 1
题目分析:
将【对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和】记为 x 操作。重复执行 x 操作,计算一定会进入死循环。死的方式有两种:
- 情况一:一直在 1 中死循环,即 1 -> 1 -> 1……
- 情况二:在历史的数据中死循环,但始终变不到 1
由于上述两种情况只会出现一种,因此,只要能确定循环是在【情况一】中进行,还是在【情况二】中进行,就能得到结果。
简单证明:
- 经过一次变化之后的最大值 9^2 * 10 = 810。变化的区间在【1,810】之间。
- 根据【鸽巢原理】,一个数变化 811 次之后,必然会形成一个循环。
- 所以,变化的过程最终会走到一个圈里面,因此可以用【快慢指针】来解决。
解法:(快慢指针)
算法思路:
当重复执行 x 的时候,数据会陷入到一个【循环】之中。而【快慢指针】有一个特性,就是在一个圆圈里,快指针总是会追上慢指针的,也就是说他们总会相遇在一个位置上。如果相遇的位置的值是 1,那么这个数一定是快乐数;如果相遇的位置不是 1 的话,那么就不是快乐数。
补充知识:如何求一个数 n 每个位置上的数字的平方和
- 把数 n 的每一位的数都提取出来,循环迭代以下步骤:
- 1.1
int t = n % 10提取个位; - 1.2
n /= 10干掉个位; 直到 n 的值变为 0;
- 1.1
- 提取每一位的时候,用一个变量 tmp 记录这一位的平方与之前提取位数的平方和:
tmp = tmp + t * t
C++ 代码演示:
class Solution {
int bitsum(int n) {
int sum = 0;
while (n) {
int t = n % 10;
sum += t * t;
n /= 10;
}
return sum;
}
public:
bool isHappy {
slow = n;
fast = (n);
(slow != fast) {
slow = (slow);
fast = ((fast));
}
slow == ;
}
};


