目录
1.题目链接:202.快乐数
2.题目描述:
编写一个算法来判断一个数 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
提示:
1 <= n <= 2^31 - 1
3.题目分析:
为了方便叙述,对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。这一个操作数我们记为x。
有题目可知,当我们不断重复x计算时,一定会出现死循环的场面,且有两种情况:
- 情况一:1->1->1->.......->
- 情况二:在历史数据中死循环,但始终到达不了1。
由于上述两种情况只会出现一种,因此,只要我们能确定循环是在情况一中进行,还是情况二中进行就能得到结果。
简单证明:
n的范围(1 <= n <= 2^31 - 1)。我们可知2^31 - 1=2147483647。我们选一个更大的数x=9999999999。我们可以对x进行一次操作最终x = 9*9*10=810。我们可以得知,无论对n怎么操作,结果都不会大于810,就是说极端情况,n最多也就进行810次操作不会出现循环数,但第811次必定出现循环数。
结论:如果出现循环数,我们可以用快慢指针区解决
4.解法(快慢指针):
算法思路:
根据上述的题目分析,我们可以知道对n进行操作,迟早会陷入一个循环圈内。
- 我们可以设置两个指针slow 和 fast。
- slow走一步,fast走两步。直到slow和fast走入循环圈。
- slow和fast走入循环圈相遇。
- 相遇后判断,slow或fast是否等于1
- 如果等于1,则是快乐数,反之则不是。
补充知识:如何求一个数n每个位置上的数的平方和。
- 把n的个位提取出来,循环迭代int t = n%10提取个位;n/10干掉个位,直到n变为0
- 提取每一位的时候,用一个变量tmp记录每一位的平方和之间提取位置的平方和 tmp += t * t;
5.C++算法代码:
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, fast = bitSum(n);
while(fast != slow)
{
fast = bitSum(bitSum(fast));
slow = bitSum(slow);
}
return slow == 1;
}
};