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

Leetcode刷题 由浅入深之哈希法——202. 快乐数

目录

(一)快乐数的C++实现

题意理解

写法一(哈希表)

写法二(栈与列表)

(二)复杂度分析

时间复杂度

空间复杂度

(三)总结


【题目链接】202.快乐数 - 力扣(LeetCode)

编写一个算法来判断一个数 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

(一)快乐数的C++实现

题意理解

        题目是为了判断一种数叫做快乐数,如果对这个数不停地求每一位平方的和,如果最终结果为1,则是快乐数。

写法一(哈希表)

解题思路:

根据题意,我们可以知道关键有以下几个:

(1)获取数的每一位并求平方的和。我们可以通过数学方式解决,假设有一个数为n,则n%10为最后一位的值,n/10为将最后一位去掉。通过不断进行这两步,我们就可以得到n这个数的每一位上的数字,设置一个变量sum将平方的和叠加起来。

(2)和的循环过程。循环条件则为快乐数的判断标准,是否为1,如果是1就返回true;如果不是1就一直进行循环。最大的问题在于如何判断一个数不可能是快乐数,也就是循环何时停止的问题

        此时,我们就需要将判断过的和存储下来,每计算出一个新的和时,就去找在前面是否出现过,如果出现过,则说明是会无限循环的,那么这个数就不可能是快乐数,此时就返回false。

        那么我们需要快速查找之前是否出现过,显然哈希表会比数组的时间效率更高一些。(哈希表的基础知识见博客Leetcode刷题 由浅入深之哈希表——349. 两个数组的交集-CSDN博客)

class Solution {
public:bool isHappy(int n) {set<int> hash_list;while(n != 1){    //控制判断是否为快乐数int sum = 0;while(n){    //遍历每一位数字int b = n % 10;n = n / 10;sum = sum + pow(b, 2);    //计算每一位平方的和}n = sum;if(hash_list.find(n) != hash_list.end())return false;    //能找到则说明是无限循环,不可能是快乐数hash_list.insert(n);}return true;}
};

写法二(栈与列表)

解题思路:

解题思路与写法一相同,只是使用的数据结构略有不同。

(1)计算完数字的每一位,可以将其存储在栈中,再不断获取栈顶元素进行求平方的和。(此题可以不需要存储,这里只是练习一下栈结构的用法)

(2)在查询新的和在之前是否出现过时,可以采用循环遍历数组的查找方法。(采用写法一的哈希表会查找更快一些,不过使用简单的数组也是可以完成题目的)

class Solution {
public:bool isHappy(int n) {vector<int> list(0);stack<int> nums;while(n != 1){while(n){    //将每一位的数字存储在栈中nums.push(n % 10);n = n / 10;}while(!nums.empty()){n = n + pow(nums.top(), 2);nums.pop();}for(auto i : list){    //迭代器遍历查找元素if(i == n)return false;}list.push_back(n);}return true;}
};

(二)复杂度分析

时间复杂度

(1)写法一:

        内层while(n)循环每次迭代都会将n除以 10,其时间复杂度为 O(lg​n)

        外层while(n != 1)根据数学证明,不会无限进行下去。在最坏情况下,时间复杂度可以近似看作 O(lgn),因为每次计算新的n时,其位数大致以对数级别减少。

(位数与数值的对数关系:一个 k 位数 n 满足 10^{k-1} \leq n< 10^k,对不等式两边取以 10 为底的对数可得 k−1≤lgn<k,也就是 k≈lg​n。)

  set哈希法的查找和插入操作的平均时间复杂度为O(logk),其中kset中元素的数量。

综上,在最坏情况下,整体时间复杂度为O(lgn)

(2)写法二:

        内层while(n)循环每次迭代都会将n除以 10,其时间复杂度为 O(lg​n)

        内层while(!nums.empty())循环用于计算栈中元素的平方和,时间复杂度同样为 O(lgn)

        内层遍历vector数组看是否已经出现过,时间复杂度为 O(k)kvector中元素的数量。

        外层while(n != 1)循环会持续运行,直到出现重复。时间复杂度可以近似看作 O(logn)

综上,在最坏情况下,整体时间复杂度为O(klgn)

空间复杂度

(1)写法一:使用set<int>存储已经出现过的数字。在最坏情况下,set中会存储所有在计算过程中出现过的不同数字。因此,空间复杂度为O(lgn)

(2)写法二:使用vector<int>stack<int>stack在每次计算新的n时会存储n的每一位,其空间复杂度为 O(lgn)。vector用于存储已经出现过的数字,在最坏情况下,空间复杂度为 O(lgn)。因此,整体空间复杂度为O(lgn)

(三)总结

(1)set类型哈希法底层实现为红黑树,查找的时间复杂度会比暴力遍历低。(set类型哈希法知识见Leetcode刷题 由浅入深之哈希表——349. 两个数组的交集-CSDN博客)

(2)注意本题目当中循环求出整数n的每位数字的方法。

学习中,诚挚希望有心者指正和交流,经验或者方法都可。

相关文章:

  • Adruino:传感器及步进电机
  • 我们分析前端生活。
  • 驱动开发硬核特训 · Day 21(上篇加强版):深入理解子系统机制与实战初探
  • 微服务架构下 MySQL 大表分库分表方案
  • 【Linux网络】构建与优化HTTP请求处理 - HttpRequest从理解到实现
  • std::mutex底层实现原理
  • Spring Boot集成RocketMQ
  • Win7 SSL证书问题
  • 【C++11】列表初始化
  • 第34课 常用快捷操作——按“空格键”旋转图元
  • 使用 binlog2sql 闪回 MySQL8 数据
  • 高精度运算(string函数)
  • 生成式AI全栈入侵:当GPT-4开始自动编写你的Next.js路由时,人类开发者该如何重新定义存在价值?
  • Java多态终极指南:从基础到高级应用
  • 前端技术个人求职简历模板
  • 股指期货成交量是单边还是双边?
  • NVIDIA GPU 计算能力与 COLMAP 编译配置指南【2025最新版!!!】
  • 【AI提示词】战略顾问
  • 侵水防触电的原理是什么? 侵水防触电算先进技术吗?-优雅草卓伊凡
  • 计算机视觉——对比YOLOv12、YOLOv11、和基于Darknet的YOLOv7的微调对比
  • 泽连斯基与特朗普进行简短会谈
  • 驻美国使馆发言人就美方希就关税问题与中方对话答记者问
  • 国铁集团:一季度全国海铁运输商品车同比增长33.62%
  • 国家市监总局:民生无小事,严打民生领域侵权假冒违法行为
  • 朝中社发表评论文章,谴责美军部署B1-B轰炸机至日本
  • 特朗普称已为俄乌问题设最后期限,届时美国态度或生变