题目解析
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 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个巢,N+1个鸽,至少有一个巢的鸽子数大于1,例如数字9999他执行快乐数是数字变化的范围是[1,243],最坏的情况在执行前面243次的时候每个位置都占了一个鸽子,但是在执行244次的时候总有一个巢穴鸽子数大于1,这个时候就变成了第二种情况形成了一个循环,得到的链是一个隐式的链表。隐式意味着我们没有实际的链表节点和指针,但数据仍然形成链表结构。起始数字是链表的头 “节点”,链中的所有其他数字都是节点。如果循环到最后数字是1,那就是快乐数,否则就不是快乐数。问题就转化为判断检测一个链表是否有环。因此我们在这里可以使用弗洛伊德循环查找算法。这个算法是两个奔跑选手,一个跑的快(一次跑两步),一个跑得慢(一次跑一步)。在龟兔赛跑的寓言中,跑的慢的称为 “乌龟”,跑得快的称为 “兔子”。
不管乌龟和兔子在循环中从哪里开始,它们最终都会相遇。这是因为兔子每走一步就向乌龟靠近一个节点(在它们的移动方向上)。
代码实现
C语言实现
int Sum(int n)
{
int sum=0;
while(n)
{
int num=n%10;
sum=sum+num*num;
n=n/10;
}
return sum;
}
bool isHappy(int n)
{
int low=n;
int fast=Sum(n);
while(low!=fast)
{
low=Sum(low);
fast=Sum(Sum(fast));
}
return low==1;
}
Java实现
class Solution {
public int Sum(int n)
{
int sum=0;
int num=0;
while(n!=0)
{
num=n%10;
sum=sum+num*num;
n=n/10;
}
return sum;
}
public boolean isHappy(int n)
{
int low=n;
int fast=Sum(n);
while(low!=fast)
{
low=Sum(low);
fast=Sum(Sum(fast));
}
return low==1;
}
}
欢迎留言讨论