题目描述
编写一个算法来判断一个数是不是“快乐数”。
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
实例:
输入: 19
输出: true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
题解:
常规方法当然是通过哈希表判重,即通过set(c++)记录每次计算得到的数来判断是否跳出循环。本文将介绍另一种方法,也就是利用Floyd Cycle思想来判断是否是1跳出循环。通俗来讲,就是快慢指针。
题目给出了快乐数的定义,注意:是快乐数最终会变成1;若不是则可能掉入死循环。意味着我们要思考如何跳出循环。这时,利用快慢指针可破循环。为什么这么说?顾名思义,可以假设快慢指针在同一起点(也就是出入值n)出发,快指针一次计算两步,慢指针一次计算一步,那么,在某一时刻,无论它是不是快乐数,快慢指针都会相遇。也就意味着循环周期结束。这时,我们可以跳出循环,判断是否是1导致跳出循环。
注:这里快慢指针分别走几步没有限制,掌握思想即可。当然,快两步慢一步效率相对高一些。
算法
class Solution {
public:
bool isHappy(int n) {
int slow = n, fast = n;
do{
slow = countNum(slow);
fast = countNum(fast);
fast = countNum(fast);
}while(slow != fast);
if(slow == 1){
return true;
}
else{
return false;
}
}
int countNum(int n ){
int sum = 0, temp = 0;
while(n > 0){
temp = n % 10;
sum += pow(temp , 2);
n = n / 10;
}
return sum;
}
};
提示:
当输入数为快乐数时,快慢指针最后一定会到达1,意味着快指针会先到达1,然后等着慢指针到达1再跳出循环。这使得我们会多出一部分运算,所以我们可以在快指针到达1时就跳出循环。
改进:
class Solution {
public:
bool isHappy(int n) {
int slow = n, fast = n;
do{
slow = countNum(slow);
fast = countNum(fast);
fast = countNum(fast);
if(fast == 1){
return true;
}
}while(slow != fast);
if(slow == 1){
return true;
}
else{
return false;
}
}
int countNum(int n ){
int sum = 0, temp = 0;
while(n > 0){
temp = n % 10;
sum += pow(temp , 2);
n = n / 10;
}
return sum;
}
};
若还有疑问可以去英文版leetcode的discuss区看大神们的解答!