题解 | #快乐数#

快乐数

https://www.nowcoder.com/practice/293b9ddd48444fa493dd17da0feb192d

题目链接

快乐数

题目描述

给定一个正整数,请你判断这个数是不是快乐数

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

示例 1: 输入: 19 输出: true 解释:

示例 2: 输入: 111 输出: false

解题思路

这道题的核心是判断一个数字经过一系列"各位数字平方和"的变换后,是最终能到达 1,还是会陷入一个无限循环。

1. 变换序列与循环 这个变换过程 n -> next_n 会生成一个数字序列。

  • 如果一个数是快乐数,这个序列的终点是 1。
  • 如果不是快乐数,序列永远不会到达 1。由于变换后的数值大小有上限(例如,对于任意一个4位数,其各位数字平方和最大为 9^2 * 4 = 324),所以序列中的数字不会无限增大,最终必然会重复某个已经出现过的数字,从而形成一个环 (Cycle)

2. 环检测 因此,这个问题就转化为了一个经典的环检测问题。我们只需要判断这个序列是最终汇入 1,还是陷入了其他循环。

最直观的环检测方法是使用哈希集合 (Hash Set)

  1. 创建一个哈希集合 seen,用来存储所有在变换过程中出现过的数字。
  2. 从给定的数字 n 开始,进入一个循环,反复计算下一个数。
  3. 在循环的每一步:
    • 首先判断当前数字 n 是否等于 1。如果是,则找到了快乐的结局,返回 true
    • 然后判断当前数字 n 是否已经在 seen 集合中。如果是,则说明我们进入了一个循环,永远无法到达 1,返回 false
    • 如果以上都不是,说明这是一个新数字,将它加入 seen 集合,然后计算出下一个数,继续循环。

为了代码清晰,我们可以将"计算各位数字平方和"的逻辑提取为一个辅助函数。

代码

class Solution {
private:
    int getNext(int n) {
        int sum = 0;
        while (n > 0) {
            int digit = n % 10;
            sum += digit * digit;
            n /= 10;
        }
        return sum;
    }

public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param n int整型
     * @return bool布尔型
     */
    bool happynum(int n) {
        set<int> seen;
        while (n != 1 && seen.find(n) == seen.end()) {
            seen.insert(n);
            n = getNext(n);
        }
        return n == 1;
    }
};
import java.util.*;

public class Solution {
    private int getNext(int n) {
        int sum = 0;
        while (n > 0) {
            int digit = n % 10;
            sum += digit * digit;
            n /= 10;
        }
        return sum;
    }

    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param n int整型
     * @return bool布尔型
     */
    public boolean happynum(int n) {
        Set<Integer> seen = new HashSet<>();
        while (n != 1 && !seen.contains(n)) {
            seen.add(n);
            n = getNext(n);
        }
        return n == 1;
    }
}
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param n int整型 
# @return bool布尔型
#
class Solution:
    def get_next(self, n: int) -> int:
        total_sum = 0
        while n > 0:
            n, digit = divmod(n, 10)
            total_sum += digit ** 2
        return total_sum

    def happynum(self, n: int) -> bool:
        # write code here
        seen = {n}
        while n != 1:
            n = self.get_next(n)
            if n in seen:
                return False
            seen.add(n)
        return True

算法及复杂度

  • 算法: 哈希集合/有序集合(用于环检测)
  • 时间复杂度:
    • C++: 。变换序列的长度约为 。对于 std::set,每次插入和查找操作需要 时间,其中 K 是集合中的元素数量(最多也为 )。
    • Java/Python: 。对于哈希表,每次操作平均时间为 ,总时间由变换序列的长度主导。
  • 空间复杂度: 。空间由集合 seen 使用。其存储的元素数量与时间复杂度的分析类似,也由 n 的位数相关。
全部评论

相关推荐

06-12 17:07
沈阳大学 Java
AAA射频小张:冬天也发扬下,我怕冷
点赞 评论 收藏
分享
06-13 17:33
门头沟学院 Java
顺序不记了,大致顺序是这样的,有的相同知识点写分开了1.基本数据类型2.基本数据类型和包装类型的区别3.==和equals区别4.ArrayList与LinkedList区别5.hashmap底层原理,put操作时会发生什么6.说出几种树型数据结构7.B树和B+树区别8.jvm加载类机制9.线程池核心参数10.创建线程池的几种方式11.callable与runnable区别12.线程池怎么回收线程13.redis三剑客14.布隆过滤器原理,不要背八股,说说真正使用时遇到了问题没有(我说没有,不知道该怎么回答了)15.堆的内存结构16.自己在写项目时有没有遇见过oom,如何处理,不要背八股,根据真实经验,我说不会17.redis死锁怎么办,watchdog机制如何发现是否锁过期18.如何避免redis红锁19.一个表性别与年龄如何加索引20.自己的项目的QPS怎么测的,有没有真正遇到大数量表21.说一说泛型22.springboot自动装配原理23.springmvc与springboot区别24.aop使用过嘛?动态代理与静态代理区别25.spring循环依赖怎么解决26.你说用过es,es如何分片,怎么存的数据,1000万条数据怎么写入库中27.你说用limit,那么在数据量大之后,如何优化28.rabbitmq如何批次发送,批量读取,答了延迟队列和线程池,都不对29.计网知不知道smtp协议,不知道写了对不对,完全听懵了30.springcloud知道嘛?只是了解反问1.做什么的?短信服务,信息量能到千万级2.对我的建议,基础不错,但是不要只背八股,多去实际开发中理解。面试官人不错,虽然没露脸,但是中间会引导我回答问题,不会的也只是说对我要求没那么高。面完问我在济宁生活有没有困难,最快什么时候到,让人事给我聊薪资了。下午人事打电话,问我27届的会不会跑路,还在想办法如何使我不跑路,不想扣我薪资等。之后我再联系吧,还挺想去的😭,我真不跑路哥😢附一张河科大幽默大专图,科大就是大专罢了
查看30道真题和解析
点赞 评论 收藏
分享
今年读完研的我无房无车无对象,月入还没有过万&nbsp;看到他在朋友圈晒房产证,感叹自己白读了这么多年书
梦想是成为七海千秋:那咋了,双9毕业的现在还没存款呢(因为没念完),高中毕业的去直播带货月入几百万也是完全有可能的,退一万步讲,有些人刚出生父母就给买车买房了,上哪说理去,哪怕是同一个起点也会有截然不同的走向,过好自己的生活就完事了。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务