面试经典150题——快乐数

news2024/10/6 0:28:12

​"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.coloradmin.cn/o/1466889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity资源加密解决方案

据统计,全球范围内超过50%的游戏均使用Unity创作而成,作为游戏开发市场第一大游戏引擎占有者,Unity已经全面覆盖到各个游戏平台。 全球游戏引擎市场占有率 由于体量庞大,Unity游戏已成为受游戏黑灰产攻击的重灾区,因游…

rider 缺少iisexpress

File C:/Program Files (x86)/IIS Express/iisexpress.exe doesn’t exist iisexpress下载 64位系统只能安装64位,32位系统安装32位 安装完成之后就有了

【Java程序设计】【C00284】基于Springboot的校园疫情防控管理系统(有论文)

基于Springboot的校园疫情防控管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的校园疫情防控系统 本系统分为系统功能模块、管理员功能模块以及学生功能模块。 系统功能模块:在系统首页可以查…

【无刷电机学习】各种电机优势比较

目录 0 参考出处 1 有刷与无刷比较 2 交流与直流比较 3 内转子与外转子比较 4 Delta型与Y型定子绕向比较 5 低压BLDC的一些优点 0 参考出处 【仅作自学记录,不出于任何商业目的。如有侵权,请联系删除,谢谢!】 维基百科…

个人简历补充

个人简历补充 1.对工作的认识2.八股文和知识面3.框架/架构角度深扒3.1 前端3.1.1 mPaaS(移动领域)3.1.2 普通前端项目框架3.1.3 微前端 3.2 后端 持续更新 1.对工作的认识 2.八股文和知识面 前端(基础知识 / 开发能力 / 总结输出能力&#xf…

易宝OA DownloadFile 任意文件读取漏洞复现

0x01 产品简介 易宝OA系统是一种专门为企业和机构的日常办公工作提供服务的综合性软件平台,具有信息管理、 流程管理 、知识管理(档案和业务管理)、协同办公等多种功能。 0x02 漏洞概述 易宝OA系统DownloadFile接口处存在任意文件读取漏洞,未授权的攻击者可以利用此漏洞…

knife4j springboot3使用

简介 在日常开发中,写接口文档是我们必不可少的,而Knife4j就是一个接口文档工具,可以看作是Swagger的升级版,但是界面比Swagger更好看,功能更丰富 使用 我使用的是springboot3.2.3 knife4j 4.3.0,knife4j 4.4版本有…

Windows 远程控制 Mac 电脑怎么操作

要从 Windows 远程控制 Mac 电脑,您可以使用内置 macOS 功能或第三方软件解决方案。以下是一些方法: 一、使用内置 macOS 功能(屏幕共享) 1、在 macOS 上启用屏幕共享 转至系统偏好设置 > 共享;选中“屏幕共享”…

Linux--自定义shell

shell shell就是操作系统提供给用户与操作系统进行交互的命令行界面。它可以理解为一个用户与操作系统之间的接口,用户可以通过输入命令来执行各种操作,如文件管理、进程控制、软件安装等。Shell还可以通过脚本编程实现自动化任务。 常见的Unix系统中使…

Vue2页面转化为Vue3

vue2element-ui转化为Vue3element plus 后台管理系统&#xff1a;增删查改 vue2页面&#xff1a; <template><div class"app-container"><div><el-form:model"queryParams"ref"queryForm"size"small":inline&qu…

小程序画布(二维地图线)

首先开始是想用小程序兼容openlayers的&#xff0c;但是了解到用不了&#xff0c;那就用画布来解决 实际效果如下 wxml中代码 <canvas id"trackDesignCanvas" //指定 id 的 Canvas 组件class"orbit-canvas-main" type"2d" …

西门子200SMART SB AE01的正确用法

西门子200SMART SB AE01&#xff0c;就是1路模拟量输入的SB板。信号板直接安装在 SR/ST CPU 本体正面&#xff0c;无需占用电控柜空间&#xff0c;安装、拆卸方便快捷。有些小型的系统如果只有1路模拟量输入&#xff0c;或者模块配置中恰好缺少1路模拟量输入&#xff0c;就可以…

幻兽帕鲁(Palworld 1.4.1)私有服务器搭建(docker版)

文章目录 说明客户端安装服务器部署1Panel安装和配置docker服务初始化设置设置开机自启动设置镜像加速 游戏服务端部署游戏服务端参数可视化配置 Palworld连接服务器问题总结 说明 服务器硬件要求&#xff1a;Linux系统/Window系统&#xff08;x86架构&#xff0c;armbian架构…

C++奇怪的 ::template

答疑解惑 怎么会有::template的写法 起初 在阅读stl的源码的时候&#xff0c;发现了一条诡异的代码 // ALIAS TEMPLATE _Rebind_alloc_t template<class _Alloc,class _Value_type> using _Rebind_alloc_t typename allocator_traits<_Alloc>::template rebind…

【视频编码\VVC】环路滤波基础知识

本文为新一代通用视频编码H.266\VVC原理、标准与实现的简化笔记。 定义&#xff1a;在视频编码过程中进行滤波&#xff0c;滤波后的图像用于后续编码。 目的&#xff1a;1、提升编码图像的质量。2、为后续编码图像提供高质量参考&#xff0c;获得更好的预测效果。 VVC中主要…

C语言-数组指针与指针数组

一、简介 对于使用C语言开发的人来说&#xff0c;指针&#xff0c;大家都是非常熟悉的。数组&#xff0c;大家也同样熟悉。但是这两个组合到一起的话&#xff0c;很多人就开始蒙圈了。这篇文章&#xff0c;就详细的介绍一下这两个概念。 指针数组和数组指针&#xff0c;听起来非…

Stable Diffusion 模型分享:Realisian(现实、亚洲人)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 Realisian 是由多个模型合并而来&#xff0c;是一个现实模型&#xff0c;可以绘制美丽的亚…

HarmonyOS学习--三方库

文章目录 一、三方库获取二、常用的三方库1. UI库&#xff1a;2. 网络库&#xff1a;3. 动画库&#xff1a; 三、使用开源三方库1. 安装与卸载2. 使用 四、问题解决1. zsh: command not found: ohpm 一、三方库获取 在Gitee网站中获取 搜索OpenHarmony-TPC仓库&#xff0c;在t…

uniapp_微信小程序自定义顶部导航栏和右侧胶囊对齐(不对齐来打我)

一、想要的效果 思路首先开启自定义导航栏&#xff0c;取消自带的导航栏&#xff0c;然后计算胶囊的高度和标题对齐 二、成品代码 1、首先再你需要居中的代码添加以下style <view class"header":style"{paddingTop:navBarTop px,height:navBarHeight px,…