(3)双指针练习:快乐数

快乐数

题目链接:202. 快乐数 - 力扣(LeetCode)

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
1. 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
2. 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
3. 如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n快乐数 就返回 true ;不是,则返回 false

思路解析:

本题根据所给条件可以推出两种情况:

  1. 结果为1
  2. 结果不为1成环

如果将结果为1的看作为环,那么可以将上面两种情况归纳为一种情况:最后的计算结果一定会在环中,如果结果为1,那么环中的所有数值均为1,如果结果不为1,那么环中即为其他数值,如图所示:

通过将题目中对上面的结果进行抽象后,可以发现结果一定会成环,联系到题目:141. 环形链表可以考虑使用双指针算法中的快慢指针解决本题目,具体思路如下:

  1. 定义一个慢指针slow和一个快指针fast
  2. slow指针走一步,fast指针走两步
  3. 因为整个过程一定会成环,所以fast和slow指针一定会在环中的某一个位置相遇,判断相遇位置的数值是否为1
💡

本题提问:除了结果为1的另一种结果就是死循环,思考是否存在一种可能结果不是成环导致的死循环,而是无限增大导致的死循环

参考代码:

/*
 * @lc app=leetcode.cn id=202 lang=cpp
 *
 * [202] 快乐数
 */

// @lc code=start
class Solution
{
public:
    int sum_digit(int num)
    {
        int sum = 0;
        while (num)
        {
            int temp = num % 10;
            sum += temp * temp;
            num /= 10;
        }
        return sum;
    }
    bool isHappy(int n)
    {
        int slow = n;
        int fast = sum_digit(n);
        while (slow != fast)
        {
            slow = sum_digit(slow);
            fast = sum_digit(sum_digit(fast));
        }

        return fast == 1;
    }
};
// @lc code=end

思考题目解析:

本题中并不会出现因为数值无限增大而导致死循环,即一定会成环,可以使用鸽巢原理进行分析:

鸽巢原理:有n个鸽子巢,有n+1个鸽子,如果将鸽子放入鸽子巢中,那么至少会存在一个鸽子巢中的鸽子数量大于或等于1

参考资料:鸽巢原理 

题目中给到的提示数字范围为INT_MAX(32位系统下),假设现在一个有一个远大于INT_MAX的数值,例如9999999999(10个9),此时该数值的和为9^2\times 10,即810,那么说明在计算快乐数时,所有的给定数值最后的结果都会出现在[1, 810]这个范围中(鸽子巢),既然如此,根据鸽巢原理,假设数字变化的次数为811(鸽子),因为范围固定,那么最后一个数值肯定会再一次出现在[1, 810]这个范围中,此时就会出现结果循环,所以一定会出现至少一个数值是重复出现导致成环,所以不存在因为数值无限增大而导致死循环

  • 40
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怡晗★

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值