面试经典150题——快乐数

​"Success is not final, failure is not fatal: It is the courage to continue that counts." - Winston Churchill

person sitting inside restaurant

1. 题目描述

image-20240223175144069

2.  题目分析与解析

2.1 思路一

还是最简单的,模拟最直观的思路,就是进行一个while循环。比如:

image-20240223182627567

根据上面的示例,可以知道while循环终止条件为各个位上的平方和为1,就可以返回true。但是对于false的情况怎么办呢?

此时就需要注意题目中提到的

image-20240223183905806

它为什么把无限循环加粗?那就是在向你透露一个信息,对于无限循环的情况那就是需要返回false的情况。

所以我们现在的目的就是找到无限循环到底是什么样的。需要找到这个无限循环的规律,那我们就得找一些出现无限循环的数来看看,也就是找到那些返回false的情况。看看题目中的测试用例:

image-20240223184225104

这不是就有一个?因此我们就可以以 2 作为突破口,看看究竟无限循环是什么意思。

image-20240223184820349

上面是以2为用例的一次次计算,发现什么了吗?

image-20240223185042756

有没有发现开始循环了?所以遇见问题不要慌,把能用的信息都用上多试一试就能解决了。

既然发现有循环了,那是不是就很好办了,我们就可以使用一个结构,存储那些循环的部分,如果在后续while过程中发现开始和循环的部分重复了,就可以判断该数不是快乐数了。

存储那些循环的部分,到底是哪部分?

既然要循环,继续看这个图:

image-20240223185514987

两个红色部分有没有看出点什么?2和20,两个就多了几个0,因此我们就可以假设出现循环的位置就是我们的当前位置的值可能加了几个0,这样才能使得他们生成的下一个数字一样。于时我根据这个思路写了代码,但是很遗憾在测试用例为3时:

image-20240223192959075

所以我又根据3作为输入,重新计算每一次的值:

image-20240223193038909

这我发现又冒出来了4这个数字,又开始循环了。直到这时我才知道原来这个数字就是出现循环返回false的条件,也就是说对于那些不是快乐数的n,它肯定会走到4开头的循环。

而我之前运行超时的假设是:

image-20240224073257877

对于任何数,如果不是快乐数,那么就会有一个轮次的固定数,也就是如上图红色一个轮次,蓝色一个轮次,这两轮除了第一个数字不一样以外其它部分全部相同,所以我在之前的代码中就去判断第1次while循环的结果和某一次是否相同,当出现相同值就说明进入了第二轮次循环,就可以返回false。所以我假设错误的结构是这样的:

image-20240224074501912

但是实际上是所有的非快乐数都会进入一个循环:4→16→37→58→89→145→42→20→4,也就是实际的结构是如下图:

fig2

现在规律找到了,那么我们就可以缕一缕代码思路了。

代码思路:

  1. 定义一个hashMap,存储平方值

  2. 进行while循环计算每一个sum,并将计算结果在最后赋值给n

  3. 当发现n等于1时,说明满足条件,返回true

  4. 当发现n等于4时,说明进入循环,返回false

总结

遇见问题多尝试,多试一试就能发现规律。开始我也没头绪,但是试着试着就找到规律了,所以还是得多动手。

2.2 思路二——判断是否循环

在这里再讲一下快慢指针法,因为我们已经知道如果某个数字不是快乐数,就肯定会出现循环,因此我们就需要判断是否有循环即可,至于这个循环是什么循环,我们并不关心。而什么是循环,循环就是当前节点连到下一个点,这样一直连下去最后还能回到当前节点,那么是不是就是一个环状结构。

因此判断一个数是不是快乐数就是判断它形成的数字链中是否有环,就是检测一个链表是否有环。这个问题怎么解决呢?

在给答案之前先来思考一下,如何判断是否会进入环?

2.2.1 思路二——1

我们是不是可以用一个定义一个hashMap,保存走过的值,如果发现某一个值开始在之前的hashMap中包含了,那么肯定下一个数字也被包含,因为相同数字的下一个数字肯定还一样。因此只要发现某一个值开始在之前的hashMap中包含了,就说明有循环。

代码思路:

  1. 定义一个hashMap,保存走过的值,定义一个hashMap,存储平方值(只为了做加速运算的作用)

  2. 进行循环,条件为如果n等于1,表示成功,那么结束循环

    • 将n存入走过的hashMap

    • 计算新的值

    • 判断之前走过的值中是否有当前的新值,如果有说明进入循环了,就需要返回false

    • 将新值赋值给 n

2.2.2 思路二——2

除了上述思路以外,还有一种方式就是假想一下两个人现在准备去操场跑步,他们准备一直在操场跑不停止。

下载

假设他们都从宿舍出发,A 8点就到了跑道开始跑步,B 10点才到跑道跑步,并且我们假设A 的速度是5m/s,B的速度是3m/s,那么A和B会相遇嘛?

答案显而易见即使他们不同时到达,而且速度不一样,但是他们肯定会相遇。那如果A的速度是100m/s,B的速度是1m/s呢?

答案还是会相遇,这是显而易见的,因为他们的速度虽然不同,但是速度差就决定了他们彼此相互靠近的速度。

因此把这种思想套用在我们的题目上,我们要判定是否出现环状结构,那么是不是就可以让两个速度不一样的人用不同的时间从宿舍去操场,开始跑步。

  • 如果这个数不是快乐数,它就不会出现循环结构,也就是说他们的跑道会变成直线跑道不是快乐数那就肯定有终点,这个终点就是出现1的情况,那么他们之间的距离肯定会不断拉大,并且跑的快的人肯定比跑的慢的人先到达终点。

images

  • 如果这个数是快乐数,那么它就会出现环状结构,就是有循环,那么他们就是围绕环形跑道进行奔跑:

那他们肯定会在某一个地方相遇,这就是终止条件。

其实上述思路就是 弗洛伊德循环查找算法

所以对于是快乐数和不是快乐数,两个不同速度的跑步者都能找到终止条件,那么程序不也一样?所以根据以上思路,我们可以写出如下代码思路。

代码思路:

  1. 假定两个速度不同的跑步者,这里的速度其实就是遍历节点的个数,假设A每次遍历两个,B每次遍历一个。那么A和B要么相遇,要么A先走到1。

  2. 定义一个hashMap,存储平方值(加速运算)

  3. while循环计算每一次的结果,终止条件为速度快的是否到达终点 1 ,或者两个跑步者是否相遇

    • 计算A跑步者每次跑步后的位置

    • 计算B跑步者每次跑步后的位置

3. 代码实现

3.1 思路一

image-20240223194011359

image-20240223193837397

3.2 思路二

3.2.1 思路二——1

image-20240224085925867

image-20240224085901306

3.2.1 思路二——2

image-20240224085840396

image-20240224085816702

4. 相关复杂度分析

4.1 思路一

时间复杂度
  1. 初始化HashMap: 初始化操作的时间复杂度为O(1),因为这里只有10个固定的映射关系被添加到HashMap中,与输入大小n无关。

  2. while循环: 这个循环的次数取决于n减小到1或者进入循环(如开始重复相同的数值)所需的迭代次数。对于快乐数问题,已知所有非快乐数最终都会进入到4, 16, 37, 58, 89, 145, 42, 20, 4的循环中。因此,循环的次数是有上限的,但是这个上限如何精确定义对于任意的n来说是不明确的。尽管如此,我们可以认为这个上限存在,从而可以认为该循环的时间复杂度是O(log n),因为每一次迭代n都会显著减小(至少在多数情况下)。

  3. 内部while循环: 这个循环用于计算n的每一位数的平方和。对于一个k位数字,这个循环将执行k次。因为k = log10(n),所以这个循环的时间复杂度是O(log n)

因此,总的时间复杂度可以被视为O(log n * log n),因为外部循环和内部循环的复杂度都是O(log n),并且它们是嵌套的。

空间复杂度
  1. HashMap: 因为HashMap中存储了10个固定的键值对,所以它的空间复杂度是O(1)

  2. 临时变量: sum和循环中的其他临时变量占用的空间是常数级别的,因此它们的空间复杂度也是O(1)

所以该函数空间复杂度是O(1),因为所需的额外空间不随输入n的大小变化而变化。

4.2 思路二

方法一分析 (isHappy2)
  • 时间复杂度:

    • 初始化squareMap的时间复杂度为O(1),因为它仅包含0到9的平方,是一个常数时间操作。

    • 主循环中,对于每个n,我们计算其数字平方和,直到n变为1或进入循环。这个过程的时间复杂度取决于n的大小和它进入循环的快慢。在最坏的情况下,这可能接近O(log n)到O(log^2 n),因为每次迭代都会减少n的大小,但是具体取决于数字的分布和循环的检测。

    • 使用numMap来检查循环的存在,每次插入和查找操作的时间复杂度为O(1)。

  • 空间复杂度:

    • squareMap的空间复杂度为O(1)。

    • numMap的空间复杂度最坏情况下为O(log n)到O(log^2 n),因为它存储了遍历过程中的每个数字,直到找到循环或达到1。

方法二分析 (isHappy3)
  • 时间复杂度:

    • 初始化squareMap与方法一相同,时间复杂度为O(1)。

    • 使用快慢指针的方法,时间复杂度主要依赖于找到循环或1所需的步数。快慢指针技巧通常用于检测链表中的循环,其效率高于简单的追踪方法,因为它减少了不必要的迭代。对于快乐数问题,这种方法能够更快地到达重复序列或结束,因此在实践中,它的时间效率通常比线性检查所有元素要好,但最坏情况下的理论时间复杂度仍然是O(log n)到O(log^2 n)。

  • 空间复杂度:

    • squareMap的空间复杂度为O(1)。

    • 与方法一不同,方法二没有使用额外的哈希映射来存储遍历过的数字,因此它的空间复杂度优于方法一,主要是O(1),因为除了几个变量之外没有存储大量数据。

总结
  • 方法一(isHappy2)的时间复杂度大约是O(log n)到O(log^2 n),空间复杂度是O(log n)到O(log^2 n)。

  • 方法二(isHappy3)的时间复杂度同样是O(log n)到O(log^2 n),但空间复杂度降低到O(1)。

方法二在空间效率上有显著优势,因为它避免了存储所有遍历过的数字。在时间效率方面,两种方法可能相似,但方法二通常更优,因为快慢指针技巧能更快地发现循环或达到1。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/487730.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle迁移到mysql-导出mysql所有索引和主键

导出建库表索引等: [rootlnpg ~]# mysqldump -ugistar -pxxx -h192.168.207.143 --no-data -d lndb > lndb20230223-1.sql 只导出索引:参考:MYSQL导出现有库中的索引脚本_mysql 导出数据库所有表的主键和索引-CSDN博客 -- MYSQL导出现有…

精品基于SpringBoot+Vue的常规应急物资管理系统

《[含文档PPT源码等]精品基于SpringBootVue的常规应急物资管理系统[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功! 软件开发环境及开发工具: Java——涉及技术: 前端使用技术&#xff…

京东数据分析|京东销售数据怎么查|京东销售数据查询软件分享!

京东销售数据分析对商家来说具有多方面的重要作用,主要体现在以下几个方面: 市场趋势分析: 分析京东平台上的商品销量、销售额和价格走势等数据,可以帮助商家了解当前市场的整体需求趋势,以及不同品类的季节性变化、…

计算机组成原理(12)----多处理系统

目录 1.SISD(单指令流单数据流) (1)特性 (2)硬件组成 2.SIMD(单指令流多数据流) (1)特性 (2)硬件组成 3.MISD(多指…

自定义Chrome的浏览器开发者工具DevTools界面的字体和样式

Chrome浏览器开发者工具默认的字体太小,想要修改但没有相关设置。 外观——字体可以自定义字体,但大小不可以调整。 github上有人给出了方法 整理为中文教程: 1.打开浏览器开发者工具,点开设置——实验,勾上红框设…

深度学习中数据的转换

原始(文本、音频、图像、视频、传感器等)数据被转化成结构化且适合机器学习算法或深度学习模型使用的格式。 原始数据转化为结构化且适合机器学习和深度学习模型使用的格式,通常需要经历以下类型的预处理和转换: 文本数据&#xf…

vue video 多个视频切换后视频不显示的解决方法

先说一下我这边的需求是视频需要轮播&#xff0c;一个人员有多个视频&#xff0c;左右轮播是轮播某个人员下的视频&#xff0c;上下切换是切换人员。 vue 代码 <el-carouselindicator-position"none"ref"carousel"arrow"always":interval&qu…

文心一言4.0 VS ChatGPT4.0 图片生成能力大比拼!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

spring boot3登录开发-3(账密登录逻辑实现)

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 内容简介 用户登录逻辑实现 创建交互对象 1.创建用户登录DTO 2.创建用户登录VO 创建自定义登录业务异…

unity ui界面优化

优化一个比较复杂的界面&#xff0c;里面有多个rt和组件。 在初次打开这个界面的时候会发生1s多的卡顿&#xff0c;还是非常严重的。 分析 通过profiler分析 1.打开界面时卡顿。 分析&#xff1a;除了update和dotween相关逻辑&#xff0c;主要在于打开时的lua function调用…

Day20_网络编程(软件结构,网络编程三要素,UDP网络编程,TCP网络编程)

文章目录 Day20 网络编程学习目标1 软件结构2 网络编程三要素2.1 IP地址和域名1、IP地址2、域名3、InetAddress类 2.2 端口号2.3 网络通信协议1、OSI参考模型和TCP/IP参考模型2、UDP协议3、TCP协议 2.4 Socket编程 3 UDP网络编程3.1 DatagramSocket和DatagramPacket1、Datagram…

【Java程序设计】【C00294】基于Springboot的车辆充电桩管理系统(有论文)

基于Springboot的车辆充电桩管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的车辆充电桩管理系统 本系统前台功能模块分为&#xff1a;首页功能和用户后台管理 后台功能模块分为&#xff1a;管理员功能和…