202. 快乐数(快慢指针)

对于任意n,可能出现以下几种情况:

  1. 最终会得到 1。
    在这里插入图片描述

  2. 最终会进入循环。
    在这里插入图片描述

  3. 值会越来越大,最后接近无穷大。
    对于第三种情况,我们可以简单的列举一下:
    在这里插入图片描述

会发现,13位数字的数位平方和最大是1053,1053是一个4位数,而4位数的数位平方和最大是324(回退到3位数),而3位数的数位平方和最大是243,因此,最终,4位数及4位数以上的数字的数位平方和都会落到243以内,因此要循环检查,如果又访问到了之前访问过的数字,则进入循环。

对于 3 位数的数字,它不可能大于 243。这意味着它要么被困在 243 以下的循环内,要么跌到 1。4 位或 4 位以上的数字在每一步都会丢失一位,直到降到 3 位为止。所以我们知道,最坏的情况下,算法可能会在 243 以下的所有数字上循环,然后回到它已经到过的一个循环或者回到 1。但它不会无限期地进行下去,所以我们排除第三种选择。

class Solution {
    public int getNext(int n) {
        int next = 0;
        int t = 0;
        while (n != 0) {
            t = n % 10;
            n = n / 10;
            next += t * t;
        }
        return next;
    }
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        while (n != 1 && !set.contains(n)) {
            set.add(n);
            n = getNext(n);
        }
        return n == 1;
    }
}

用集合解答这道题存在一定问题,因为题目限定n是int类型,用集合记录每次的计算结果来判断是否进入循环,这个集合可能大到无法存储。

因此使用快慢指针来实现循环判断。慢指针走一步,快指针走两步。

class Solution {
    public int getNext(int n) {
        int next = 0;
        int t = 0;
        while (n != 0) {
            t = n % 10;
            n = n / 10;
            next += t * t;
        }
        return next;
    }
    public boolean isHappy(int n) {
        int slow = n, fast = n;
        do {
            slow = getNext(slow);
            fast = getNext(fast);
            fast = getNext(fast);
        } while (slow != fast);

        return slow == 1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值