[C++算法]快乐数

题目描述:

题目来源:力扣「快乐数」

题目描述:

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

**「快乐数」**定义为:

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

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

示例 1: 输入 n = 19,返回 true。计算过程如下:

  • 1² + 9² = 82
  • 8² + 2² = 68
  • 6² + 8² = 100
  • 1² + 0² + 0² = 1

最终结果为 1,因此 19 是快乐数。

示例 2: 输入 n = 2,返回 false。计算过程如下:

  • 2² = 4
  • 4² = 16
  • 1² + 6² = 37
  • 3² + 7² = 58
  • 5² + 8² = 89
  • 8² + 9² = 145
  • 1² + 4² + 5² = 42
  • 4² + 2² = 20
  • 2² + 0² = 4

可以看到,数值进入 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 的循环,始终无法变为 1,因此 2 不是快乐数。

边界情况: 当 n = 1 时,1² = 1,直接满足条件,无需任何迭代即可返回 true。

算法原理:

类比判断链表是否有环

解法:快慢双指针

1.定义快慢双指针

2.慢指针每次移动一步快指针每次移动两步

3.判断相遇的数的值即可。值为1则为快乐数

双指针仅仅是一个思想,我们可以用数组的下标充当指针,某一个数充当一个指针。

cpp 复制代码
class Solution 
{
   int clsum(int  n)//返回n这个数的每一位的平方和
   {
        int sum =0;
        while(n)
        {        
            int t =n%10; //
            sum+=t*t;
            n/=10;
        }
        return sum;
   }
public:
    bool isHappy(int n) 
    {
        int slow =n;
        int fast =clsum(n);
        while(slow!=fast)
        {
            slow=clsum(slow); //slow走一步
            fast =clsum(clsum(fast));//fast走两步
        }
        return fast==1;
    }
};

复杂度分析:

该快慢双指针解法的时间复杂度为 O(log n),空间复杂度为 O(1)。

为什么时间复杂度是 O(log n) 而不是 O(n)?关键在于 clsum 函数对每个数求各位数字平方和的过程。对于一个 k 位数,clsum 需要执行 k 次循环,而 k = log10(n),因此单次计算平方和的代价是 O(log n)。

更重要的是,快乐数序列中的数值会迅速缩小。以最大的 10 位数 9999999999 为例,其各位平方和为 9² × 10 = 810,也就是说,无论初始的 n 有多大,经过一次 clsum 之后,数值都会立刻降到 810 以下。此后所有参与计算的数都落在 [1, 810] 这个有限区间内,快慢指针最多在这个区间内循环若干次就会相遇,循环次数是一个与 n 的位数无关的常数。

因此,总时间复杂度 = 常数次循环 × 每次 O(log n) 的平方和计算 = O(log n)。如果误以为是 O(n),通常是忽略了「平方和运算会迅速压缩数值范围」这一关键性质,误把循环次数当成了与 n 成正比。

相关推荐
武子康1 小时前
驾驶轨迹换个坐标,就能给移动机器人用吗?
人工智能·算法·机器学习
David猪大卫2 小时前
【C++修炼】map 和 set 的使用
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
HPtiger2 小时前
C++ 入门笔记:从 C 到 C++ 的核心过渡(命名空间、输入输出、缺省参数、重载、引用、内联)
c语言·c++·学习
vvilkim3 小时前
数据结构类型、区别与应用场景:一篇讲透选型逻辑
数据结构
努力努力再努力wz5 小时前
【Lua 进阶系列】从 C++ 对象到 Lua 变量:一文理解 userdata、Lua 栈与元表绑定机制
c++·junit·lua
慧都产品智能化5 小时前
Qt 表格升级攻略:复用已有编辑器,减少重复开发
c++·qt·编辑器·qt6.3
ShineWinsu5 小时前
对于Qt:QTableWidget常见属性以及QTableWidgetItem类的解析
开发语言·c++·qt·gui·客户端·表格·qtablewidget
ShineWinsu7 小时前
对于Qt:QListWidget常见属性以及QListWidgetItem类的解析
开发语言·c++·qt·客户端·列表·qlistwidget·qlistwidgetitem
坤坤子吖7 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
lisw057 小时前
Dayhoff的PAM替换矩阵理论评介!
线性代数·算法·矩阵