快乐数
编写一个算法来判断一个数
n
是不是快乐数。「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果
n
是 快乐数 就返回true
;不是,则返回false
。示例 1:
输⼊: n = 19
输出: true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:
输入:n = 2
输出:false
解释:
2 * 2 = 4
4 * 4 = 16
1 * 1 + 6 * 6 = 37
3 * 3 + 7 * 7 = 58
5 * 5 + 8 * 8 = 89
8 * 8 + 9 * 9 = 145
1 * 1 + 4 * 4 + 5 * 5 = 42
4 * 4 + 2 * 2 = 20
2 * 2 = 4
…
题目分析
为了⽅便叙述,将"对于⼀个正整数,每⼀次将该数替换为它每个位置上的数字的平⽅和"这⼀个操作记为 x 操作.
题⽬告诉我们,当我们不断重复 x 操作的时候,计算⼀定会「死循环」,循环的情况有两种:
-
⼀直在 1 中死循环,即 1 -> 1 -> 1 -> 1…
-
在历史的数据中死循环,但始终变不到1
由于上述两种情况只会出现⼀种,因此,只要我们能确定循环是在情况⼀中进⾏,还是在情况⼆中进⾏,就能得到结果。
可能这里就会有人疑问, 是否还有第三种情况, 就是这个数一直在变化, 没有循环?
实则不存在这种情况!
根据"鸽巢原理",⼀个数变化 811 次之后,必然会形成⼀个循环
因此,变化的过程最终会⾛到⼀个圈⾥⾯,因此可以⽤"快慢指针"来解决
算法思路
根据上述的题⽬分析,我们可以知道,当重复执⾏ x 的时候,数据会陷⼊到⼀个"循环"之中。
而"快慢指针"有⼀个特性,就是在⼀个圆圈中,快指针总是会追上慢指针的,也就是说他们总会相遇在⼀个位置上。如果相遇位置的值是 1 ,那么这个数⼀定是快乐数;如果相遇位置不是 1 的话,那么就不是快乐数.
Java代码
class Solution {
private int bitSum(int n) {
int sum = 0;
while(n != 0) {
int m = n % 10;
sum += m * m;
n /= 10;
}
return sum;
}
public boolean isHappy(int n) {
int low = n;
int fast = n;
//由于一开始把他们都赋值成了n, 所以循环不能直接进, 可以使用do while.
do {
low = bitSum(low);
for (int i = 0; i < 2; i++) {
fast = bitSum(fast);
}
} while (low != fast);
return low == 1;
}
}