双指针---快乐数

题目链接 快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
在这里插入图片描述

问题分析

为了⽅便叙述,将「对于⼀个正整数,每⼀次将该数替换为它每个位置上的数字的平⽅和」这⼀个操作记为quadSum操作;
题⽬告诉我们,当我们不断重复quadSum操作的时候,计算⼀定会「死循环」,⽅式有两种:
▪ 情况⼀:⼀直在 1 中死循环,即 1 -> 1 -> 1 -> 1…
▪ 情况⼆:在历史的数据中死循环,但始终变不到 1
由于上述两种情况只会出现⼀种,因此,只要我们能确定循环是在「情况⼀」中进⾏,还是在「情况⼆」中进⾏,就能得到结果。

此时,问题被抽象,可以联想到 链表是否有环 的判断,确定使用「快慢指针」

根据鸽巢原理可简单证明,肯定会出现循环
经过⼀次变化之后的最⼤值 9^2 * 10 = 810 ( 2^31-1=2147483647 。选⼀个更⼤的最
⼤ 9999999999 ),也就是变化的区间在 [1, 810] 之间;
根据「鸽巢原理」,⼀个数变化 811 次之后,必然会形成⼀个循环;

变化的过程最终会⾛到⼀个环⾥⾯,因此可以⽤「快慢指针」来解决

根据上述的题⽬分析,我们可以知道,数据会陷⼊到⼀个「循环」之中。⽽「快慢指针」有⼀个特性,就是在⼀个圆圈中,快指针总是会追上慢指针的,也就是说他们总会相遇在⼀个位置上。如果相遇位置的值是 1 ,那么这个数⼀定是快乐数;如果相遇位置不是 1 的话,那么就不是快乐数。

补充知识:如何求⼀个数n每个位置上的数字的平⽅和。
把数 n 每⼀位的数提取出来:循环迭代下⾯步骤:
i. int t = n % 10 提取个位;
ii. n /= 10 去掉个位;
直到 n 的值变为 0 ;

提取每⼀位的时候,⽤⼀个变量 tmp 记录这⼀位的平⽅与之前提取位数的平⽅和
▪ tmp = tmp + t * t

代码解决

class Solution {
    public int quadSum(int n){
int tmp = 0;
        while(n>0){
        int t = n%10;
         tmp += t*t;
        n /= 10;
        }
return tmp;
    }
    public boolean isHappy(int n) {
        int slow = n,fast = quadSum(n);
        while(slow != fast){
            slow = quadSum(slow);
            fast = quadSum(quadSum(fast));
        }
        return slow == 1;
    }
}

执行用时

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值