(笔记自用)LeetCode:快乐数

1.题目概述

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

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n快乐数 就返回 true ;不是,则返回 false

示例 1:

复制代码
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

复制代码
输入:n = 2
输出:false

提示:

  • 1 <= n <= 231 - 1

2.题目分析

快乐数的定义是基于一个计算过程,即对一个正整数,不断将其替换为它各个位上数字的平方和,如果最终这个过程能够收敛到1,则这个数被称为快乐数。相反,如果在这个过程中形成了一个不包含1的循环,则该数不是快乐数。对于非快乐数,它们的平方和序列会进入一个固定的循环,例如4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4。

为了证明每个循环的数字都是一样的,我们可以使用数学中的不动点理论。在一个有限的系统中,重复应用一个确定的操作最终会达到一个循环,这是因为系统的状态是有限的。在快乐数的情况下,由于每次计算都是基于有限的数字(0-9)的平方,因此可能的结果也是有限的。这意味着,如果我们从某个数字开始,不断重复计算它的各位数字的平方和,最终必然会进入一个循环,因为可能的平方和是有限的,而且每次计算都是确定性的。

此外,由于每个非快乐数都会进入一个固定的循环,而这个循环不包含1,这意味着循环中的所有数字都是固定的,并且每次遇到同一个数字时,都会得到相同的下一个数字。这就是为什么每个循环的数字都是一样的。

综上所述,我们可以得出结论,对于非快乐数,它们在重复计算各位数字的平方和的过程中不仅会形成一个循环,而且每个循环中的数字都是一样的。这一结论是基于有限性原理和确定性操作的重复应用。

因此我们可以使用哈希表和快慢指针来解决问题。

注意:此题不建议用集合记录每次的计算结果来判断是否进入循环,因为这个集合可能大到无法存储;另外,也不建议使用递归,同理,如果递归层次较深,会直接导致调用栈崩溃。不要因为这个题目给出的整数是 int 型而投机取巧。

3.题解

1.哈希表法

cpp 复制代码
int getSum(int n) 
{
    int sum = 0;
    while (n) 
    {
        sum += (n % 10) * (n % 10);
        n /= 10;
    }
    return sum;
}

bool isHappy(int n){
    int sum = getSum(n);
    int hash[820] = {0};

    //核心思想:若某个数字重复出现了,则这个数字永远不可能会等于1
    while (sum != 1) 
    {
        if (hash[sum] == 1) 
            return false;
        else 
            hash[sum]++;
        sum = getSum(sum);
    }
    return true;
}

2.快慢指针

cpp 复制代码
int getSum(int n) 
{
    int sum = 0;
    while (n) 
    {
        sum += (n % 10) * (n % 10);
        n /= 10;
    }
    return sum;
}

bool isHappy(int n){
    int slow = getSum(n);       //慢指针走一步
    int fast = getSum(slow);    //快指针走两步

    while(1)
    {
        if( slow==1 || fast==1 )
            return true;
        if(slow == fast)
            return false;
        slow=getSum(slow);  //走一步
        fast=getSum(getSum(fast));  //走两步
    }
}
相关推荐
还听珊瑚海吗7 分钟前
数据结构——二叉树
数据结构·算法
码尔泰26 分钟前
union 的定义和基本结构以及用途
c语言·union·联合体
小灰灰爱代码26 分钟前
C++——求3*3矩阵主对角元素之和。
c++·算法·矩阵
waterHBO34 分钟前
TensorFlow 笔记
人工智能·笔记·tensorflow
鱼跃鹰飞1 小时前
Leetcode面试经典150题-94.二叉树的中序遍历
算法·leetcode·面试
Roam-G1 小时前
Java 中常用的排序算法
数据结构·算法·排序算法
hjxxlsx1 小时前
插入与冒泡排序(C++)
c++·算法·排序算法
Skrrapper1 小时前
【数据结构】排序算法系列——快速排序(附源码+图解)
c语言·数据结构·算法·排序算法
Mephisto.java1 小时前
【力扣 | SQL题 | 每日三题】力扣175, 176, 181
sql·算法·leetcode
木向1 小时前
leetcode第十二题:整数转罗马数字
c++·算法·leetcode·职场和发展