Ciallo~(∠・ω< )⌒☆ ~ 今天,我将和大家一起做一道双指针算法题--快乐数~
目录
[一 题目](#一 题目)
[二 算法解析](#二 算法解析)
[三 编写算法](#三 编写算法)
一 题目
二 算法解析
题⽬告诉我们,当我们不断重复操作后,⼀定会出现死循环,有两种情况:
- 情况⼀:⼀直在 1 中死循环,即 1 -> 1 -> 1 -> 1......。
- 情况⼆:在历史的数据中死循环,但始终变不到 1。
因此,只要我们能确定循环中是否一直为1,就能得到结果。
那会不会出现一直没有循环的情况呢~ 以下是一个小证明~:
(鸽巢原理):有n+1个鸽子,n个巢,则至少有一个巢的鸽子数大于1。
- 经过⼀次变化之后的最⼤值 9^2 * 10 = 810 ( 2^31-1=2147483647 。选⼀个更⼤的最⼤ 9999999999 ),也就是变化的区间在 [1, 810] 之间;
- 根据鸽巢原理,⼀个数变化 811 次之后,必然会出现重复数;
- 因此,变化的过程最终会⾛到⼀个圈⾥⾯,因此可以⽤快慢指针来解决。
算法思路:
此题有点像链表带环问题,可以用快慢双指针 来求解,快慢指针有⼀个特性,就是在⼀个圆圈中,快指针总是会追上慢指针的 ,也就是说他们总会相遇在⼀个位置上。如果相遇位置的值是 1 ,那么这个数⼀定是快乐数;如果相遇位置不是 1 的话,那么就不是快乐数。
三 编写算法
cpp
class Solution {
public:
int bitsum(int x) // 返回n这个数每⼀位上的平⽅和
{
int tmp = 0;
int sum = 0;
while (x)
{
tmp = x % 10;
sum += tmp * tmp;
x /= 10;
}
return sum;
}
bool isHappy(int n)
{
int slow = n, fast = bitsum(n); //若fast也是n的话就不会进循环
while (slow != fast)
{
slow = bitsum(slow);
fast = bitsum(bitsum(fast));
}
return slow == 1;
}
};