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

leetcode 面试经典 150 题:快乐数

链接快乐数
题序号202
题型数组
解题方法哈希表
难度简单
熟练度✅✅✅✅

题目

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

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

  • 示例 1:
    输入:n = 19
    输出:true
    解释:
    12 + 92 = 82
    82 + 22 = 68
    62 + 82 = 100
    12+ 02 + 02 = 1

  • 示例 2:
    输入:n = 2
    输出:false

  • 提示:
    1 <= n <= 231 - 1

题解

  1. 核心思想:使用哈希表来记录已经出现过的数字,如果在计算过程中某个数字重复出现,说明进入了循环,返回 false;如果最终计算结果为 1,返回 true。
  2. 复杂度:时间复杂度O(logn),因为每次计算下一个数的时间复杂度为 O(logn);空间复杂度O(1),不需要额外的存储空间。
  3. c++ 实现算法
class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> seen; // 用于存储已经出现过的数字,检测循环
        
        //如果 find(n) 返回 seen.end(),表示 n 不存在于集合中,查找失败。
        //如果 find(n) 返回的迭代器不是 seen.end(),表示 n 存在于集合中,查找成功。
        while (n != 1 && seen.find(n) == seen.end()) {
            seen.insert(n);     // 将当前数字加入集合
            n = getNext(n);     // 计算下一步的平方和
        }
        return n == 1;          // 如果 n == 1,返回 true;否则进入循环,返回 false
    }

private:
    int getNext(int n) {
        int sum = 0;
        while (n > 0) {
            int digit = n % 10; // 提取个位数,如果 n = 123,则 digit = 123 % 10 = 3
            sum += digit * digit; // 累加平方
            n /= 10;             // 去掉个位,如果 n = 123,执行 n /= 10 后,n = 12
        }
        return sum;
    }
};
  1. 算法推演
  • 初始值: 输入数字:n = 2 seen 集合:空集合 {}

  • 第一步:计算平方和
    当前数字:n = 2
    计算平方和: 22=4
    更新数字:n = 4 检查 4 是否在 seen 集合中:否,将 4 加入集合。
    集合更新为:{2}

  • 第二步:计算平方和
    当前数字:n = 4
    计算平方和: 42=16
    更新数字:n = 16 检查 16 是否在 seen 集合中:否,将 16 加入集合。
    集合更新为:{2, 4}

  • 第三步:计算平方和
    当前数字:n = 16
    计算平方和: 12+62=37
    更新数字:n = 37 检查 37 是否在 seen 集合中:否,将 37 加入集合。
    集合更新为:{2, 4, 16}

  • 第四步:计算平方和
    当前数字:n = 37
    计算平方和: 32+72=58
    更新数字:n = 58 检查 58 是否在 seen 集合中:否,将 58 加入集合。
    集合更新为:{2, 4, 16, 37}

  • 第五步:计算平方和
    当前数字:n = 58
    计算平方和: 52+82=89
    更新数字:n = 89 检查 89 是否在 seen 集合中:否,将 89 加入集合。
    集合更新为:{2, 4, 16, 37, 58}

  • 第六步:计算平方和
    当前数字:n = 89
    计算平方和: 82+92=145
    更新数字:n = 145 检查 145 是否在 seen 集合中:否,将 145 加入集合。
    集合更新为:{2, 4, 16, 37, 58, 89}

  • 第七步:计算平方和
    当前数字:n = 145
    计算平方和: 12+42+52=42
    更新数字:n = 42 检查 42 是否在 seen 集合中:否,将 42 加入集合。
    集合更新为:{2, 4, 16, 37, 58, 89, 145}

  • 第八步:计算平方和
    当前数字:n = 42
    计算平方和: 42+22=20
    更新数字:n = 20 检查 20 是否在 seen 集合中:否,将 20 加入集合。
    集合更新为:{2, 4, 16, 37, 58, 89, 145, 42}

  • 第九步:计算平方和
    当前数字:n = 20
    计算平方和: 22+02=4
    更新数字:n = 4 检查 4 是否在 seen 集合中:是,说明进入循环。

  • 结论
    输入 2 会进入循环,无法到达 1,因此 2 不是一个快乐数。

  • 循环检测
    通过集合 seen,我们检测到了循环路径: 2 → 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 (循环) 这是算法检测非快乐数的重要机制,避免了死循环。

  1. c++ 完整demo
#include <iostream>
#include <unordered_set>
using namespace std;

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> seen; // 用于存储已经出现过的数字,检测循环
        
        //如果 find(n) 返回 seen.end(),表示 n 不存在于集合中,查找失败。
        //如果 find(n) 返回的迭代器不是 seen.end(),表示 n 存在于集合中,查找成功。
        while (n != 1 && seen.find(n) == seen.end()) {
            seen.insert(n);     // 将当前数字加入集合
            n = getNext(n);     // 计算下一步的平方和
        }
        return n == 1;          // 如果 n == 1,返回 true;否则进入循环,返回 false
    }

private:
    int getNext(int n) {
        int sum = 0;
        while (n > 0) {
            int digit = n % 10; // 提取个位数,如果 n = 123,则 digit = 123 % 10 = 3
            sum += digit * digit; // 累加平方
            n /= 10;             // 去掉个位,如果 n = 123,执行 n /= 10 后,n = 12
        }
        return sum;
    }
};

int main() {
    Solution solution;
    int n = 2;
    if (solution.isHappy(n)) {
        cout << n << " is a happy number!" << endl;
    } else {
        cout << n << " is not a happy number!" << endl;
    }
    return 0;
}

http://www.kler.cn/a/503210.html

相关文章:

  • 七大排序算法(Java,便于理解)
  • Angular-生命周期及钩子函数
  • 20250112面试鸭特训营第20天
  • 【HarmonyOS之旅】基于ArkTS开发(二) -> UI开发二
  • C#学习笔记 --- 简单应用
  • 在 Safari 浏览器中,快速将页面恢复到 100% 缩放(也就是默认尺寸)Command (⌘) + 0 (零)
  • 云服务信息安全管理体系认证,守护云端安全
  • npm、yarn、pnpm包安装器差异性对比
  • 深度学习中的卷积神经网络(CNN):原理与应用详解
  • 如何使用虚拟机连接到SSH
  • 【0x005B】HCI_Write_Default_Erroneous_Data_Reporting命令详解
  • 【Pandas】pandas Series radd
  • 基于Springboot + vue实现的文档管理系统
  • flutter 装饰类【BoxDecoration】
  • 上传自己的镜像到docker hub详细教程
  • 浅谈云计算06 | 云管理系统架构
  • 论文阅读:《Whole-animal connectomes of both Caenorhabditis elegans sexes》
  • 7.STM32F407ZGT6-RTC
  • 施耐德M241与MR20-MT-1616的组态过程
  • python-leetcode-矩阵置零
  • 当自动包布机遇上Profinet转ModbusTCP网关,“妙啊”,工业智能“前景无限
  • SpiderFlow平台v0.5.0之引入selenium插件
  • linux 文件权限设置详解
  • 一些实用的工具
  • Termora跨平台 SSH/SFTP/Terminal 客户端工具
  • 如何给即将满的 C 盘添加磁盘空间