import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 
     * @return bool布尔型
     */
    public boolean happynum (int n) {
        // write code here
        int slow=n;
        int fast=n;//定义快慢指针,都为一开始的数
        //使用do while形式,先走一次,然后再判断
        do{
            slow=bitNum(slow);//走一步
            fast=bitNum(bitNum(fast));//走两步

        }while(slow!=fast);//不相等就没有相遇,相遇就结束循环
        return slow==1;//相遇的时候看是不是等于1就能找到是否为快乐数了


    }
    public int bitNum(int x){//得到当前数的下一个数(走一步),平方和相加
    int num=0;
    while(x!=0){//个位数/10等于0,退出循环
        num+=(x%10)*(x%10);//得到每一位的平方
        x=x/10;//去到下一位的数
    }
    return num;//把结果返回即可
    }
}

题解:

--->对于最终的结果我们可以知道,最后一定会进入一个循环,要不是1的循环,要不就是其他不同数的循环

--->至于为什么一定会进入循环,我们在最后讲解

---->总结为以下两种情况,最后结合为一种情况--->进入循环

--->对于循环的判断,我们只要使用快慢指针的方式即可,快指针每次走两步,慢指针每次走一步

--->相遇,代表一定是一个环,不相遇代表不是环(这里我们已经知道了最后是环,所以一定会相遇)

--->然后判断相遇的时候快慢指针的值是不是都是1就行,是1就是快乐数,不是1就不是快乐数

--->这里的指针只是一种称呼,在这里我们可以使用最开始的数当作指针,比如说,一开始是2,我们让快慢指针一开始都是2然后让快指针一下变化两次,慢指针一下变化一次

-->为什么一定会进入到循环

根据鸽巢原理:有n个鸽巢,n+1个鸽子,把鸽子放入鸽巢中,---->至少有一个鸽巢里面的鸽子数量大于1

--->我们先把每一个鸽巢放入一个鸽子,剩下的一个放入,肯定会有一个大于1

-->这里也同理我们一开始的数取能取到的最大值:因为n是有取值范围的,就假设最大值是999999999(10个9)-->假设,真的自己算

--->假设n为999999999,然后他的下一次的数是10个9的平方和为810

所以我们可以得到我们的所有的数经过平方求和之后取值范围是【1,810】,因为我们最大的一个数都才得到810,那么其他的一定会小于它的,

--->假设一个开始的数因为运气好,走了(平方求和)810次都没有重复(填满了区间),那么第811次一定会重新回到区间内部,这是不是就循环