当前位置: 首页 > news >正文

【双指针专题】之快乐数

一、题目描述

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

快乐数 定义为:

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

示例 1:

输入: n = 19  
输出: true  
解释:  
19 -> 1*1 + 9*9 = 82  
82 -> 8*8 + 2*2 = 68  
68 -> 6*6 + 8*8 = 100  
100 -> 1*1 + 0*0 + 0*0 = 1

示例 2:

输入: n = 2  
输出: false  
解释:  
2 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16 


二、思路引导:双指针 / 快慢指针

快乐数 的关键在于判断过程中是否进入了一个循环。我们可以用两种方式来判断:

  1. 判断是否变为 1
  2. 判断是否进入无限循环

对于第二种情况,我们可以利用 快慢指针。因为如果一个数进入了循环,快指针必然会追上慢指针若快慢指针相遇,并且相遇位置的值是 1,则这个数是快乐数;否则就不是

快慢指针原理

  • 慢指针 每次执行一次平方和操作;
  • 快指针 每次执行两次平方和操作;
  • 如果快指针和慢指针相遇,说明数进入了循环。
  • 如果相遇点是 1,那么这个数是快乐数;如果不是 1,则说明进入了一个死循环。

三、算法流程

步骤 1:定义平方和函数

为了判断一个数是否是快乐数,我们需要一个函数来计算该数每一位的平方和

步骤 2:使用快慢指针

  • 初始化慢指针 slow = n,快指针 fast = Sum(n),其中 Sum 为平方和函数

  • 循环执行以下步骤,直到慢指针和快指针相遇

    • 慢指针执行一次平方和操作:slow = Sum(slow)

    • 快指针执行两次平方和操作:fast = Sum(Sum(fast))

  • 如果慢指针和快指针相遇时,值是 1,说明这是一个快乐数;否则,它不是快乐数。


四、代码实现(C++)

class Solution {
public:// 返回 n 这个数每一位上的平方和int Sum(int n){int sum = 0;// 循环提取每一位的数字while (n){int t = n % 10;   // 提取当前数字的个位sum += t * t;      // 将该数字的平方加到总和中n /= 10;           // 去掉个位数字,继续处理剩余的部分}return sum;  // 返回数字每一位的平方和}bool isHappy(int n){int slow = n, fast = Sum(n);   // 慢指针从 n 开始,快指针从平方和开始// 当慢指针和快指针相遇时,判断是否进入了循环while (slow != fast){slow = Sum(slow);             // 慢指针每次计算一次平方和fast = Sum(Sum(fast));       // 快指针每次计算两次平方和}// 如果相遇点为 1,则返回 true,表示该数是快乐数;否则返回 falsereturn slow == 1;  // 如果慢指针和快指针相遇,并且值是 1,表示该数是快乐数}
};

Sum 函数

  • 该函数用于计算给定数 n 每一位上的平方和。通过循环逐位提取数字,计算平方并累加。
  • 使用 % 10 提取数字的最后一位,n /= 10 去掉当前位。

isHappy 函数

  • 初始化 慢指针 (slow) 为 n快指针 (fast) 为 Sum(n)(即 n 的每位平方和)。
  • while 循环中,通过 快慢指针 逐步推进,快指针每次执行两次平方和操作,而慢指针执行一次。
  • 如果快慢指针相遇,则表示已经进入循环。此时若值为 1,则返回 true,表示该数是快乐数;否则返回 false,表示进入了无法到达 1 的死循环。

五、代码剖析与细节问题

1. 如何计算每一位的平方和?

我们需要逐位提取数的每一位,使用 n % 10 来提取个位,然后计算平方并加到总和中,最后将 n /= 10 以去掉个位。这个过程会一直进行,直到 n0

2. 为什么使用快慢指针?

当数进入无限循环时,快指针会追上慢指针。如果快指针在某次相遇时是 1,则返回 true,表示是快乐数;如果相遇位置不是 1,则返回 false,说明这个数进入了循环。

3. 循环检测的效率如何?

使用快慢指针的好处在于,通过 两次平方和操作,快指针能更快地检测到循环,减少了计算量,确保了算法的高效性。

4. 为什么要判断相遇位置是否是 1 ?

  • 如果相遇位置是 1,表示从此之后快慢指针会一直在 1 上循环,这时说明 n 是快乐数。
  • 如果相遇位置不是 1,则表示数已经陷入了循环并且无法变成 1,所以不是快乐数。

六、复杂度分析

  • 时间复杂度:O(log n)

每次计算平方和时,操作的次数是 n 的对数级别,因为数字每次递减一次。通过快慢指针的方式,时间复杂度接近 O(log n)

  • 空间复杂度:O(1)

只使用了常数级别的空间来存储慢指针和快指针,因此空间复杂度为 O(1)


七、总结

这道题不仅考察了如何使用快慢指针来解决循环问题,还加深了对 快慢指针 技巧的理解。通过将 快乐数 问题转化为 循环检测,我们能够快速判断一个数是否是快乐数。

实际应用

  • 环形链表问题: 快慢指针常用于检测环形链表问题,能够高效判断链表是否有环

  • 链表相交点: 快慢指针还可以用来找出两个链表的交点,通过设定不同的起始点并同时移动,最终可以找到交点。

笔者的话:快乐数是一道经典的题目,通过这道题,读者可以熟悉如何用 快慢指针 解决循环检测问题。掌握了这个技巧,在其他类似问题上也会有更多的灵感。

http://www.dtcms.com/a/438761.html

相关文章:

  • 锦州滨海新区城市建设规划网站建设局是个好单位吗
  • 域名搭建网站域名一般在哪里购买
  • 拦截器Interceptor
  • 运营网站流程ui设计的定义
  • 可以做自己的单机网站网站客户案例的
  • 网络编程中UDP协议的广播和组播通信
  • STM32G474单片机开发入门(一)STM32G474RET6单片机详解
  • W3C 简介
  • 菲律宾宿务Cebu(宿雾)介绍
  • Python中如何实现多级缓存
  • 深入掌握 FluentMigrator:C#.NET 数据库迁移框架详解
  • 快速做网站套餐光谷网站建设哪家好
  • 基本定时器(TIM6、TIM7)的基本介绍
  • 荆州网站建设兼职旅游网站功能简介
  • 有关做美食的网站android源码下载网站
  • Ubuntu中部署docker教程及使用指南(易用版)
  • c++之基础A(系统函数)(第一课)
  • 使用scrollview 时,自动滚动条和视图大于子view时居中显示
  • 如何最小阻力练习软件测试相关的英语口语
  • 专门做视频点评的网站iis 新建网站没有文件夹权限
  • 【完整源码+数据集+部署教程】 小麦病害分割系统: yolov8-seg-dyhead
  • Java 黑马程序员学习笔记(进阶篇16)
  • 自适应网站功能网站开发开发的前景
  • 整套网站设计网络服务费
  • python autocad comtypes+pyautocad二次开发 pywin32连不上高版本cad解决办法
  • Linux——0:安装与配置、命令、gcc
  • 健康管理实训室:创新教学场景,推动健康管理人才实战能力提升
  • 网站建设设计模板工业设计 做自己的网站 知乎
  • CAN-FIFO 确认处理(FIFO Acknowledge Handling)
  • Java--多线程知识(四)