【Leetcode哈希表 202. 快乐数】C++

🎈个人主页:算法诗人
✨收录专栏:算法诗人Leetcode揭秘之旅
🎉欢迎 👍点赞✍评论⭐收藏
🤝希望我的文章能对你们有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗



Leetcode题目链接

202. 快乐数


一、题目描述

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

示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000

二、解题思路

题中判断一个数是否为快乐数的依据是这个求和的过程是否会无限循环,如果我们找到一个和值sum会重复出现且不为1,则表示这个数就不是快乐数;如果和值会变为1,则表示这个数为快乐数。

当我们遇到了要快速判断一个元素是否出现集合里的时候,并且这里的循环次数我们无法确定时,我们就要考虑用到哈希表,本题用到的是unordered_set类型。

unordered_set 是 C++ STL(标准模板库)中的一个容器,它是一个集合(Set)的实现,但与 set 不同,unordered_set 中的元素是无序的。这是通过哈希表实现的,因此查找、插入和删除等操作的平均时间复杂度是 O(1)。

如果sum重复出现了return false, 否则一直求和直到sum为1。

本题的难点在如何计算一个位数未知的正整数每一个位的平方和。
这里要用到取余和整数除法,这里是一次求和的过程,具体在代码部分会写到。
解题思路

三、示例代码

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> set;
        while(1)//一直循环直到sum重复或者为1
        {
            int sum = 0;
            while(n)//判断n的每一位数是否计算完
                {
                    sum = sum + pow(n % 10, 2);//将当前位的平方和加到sum中
                    n = n / 10;//每计算一位后换到下一位准备进行下一位的运算
                }
            if(sum == 1)//判断此次sum是否为1
            {
                return true;
            }

            if(set.find(sum) != set.end())//判断此次sum是否重复出现
            {
                return false;
            }
            else
            {
                set.insert(sum);//此次sum不在set中则添加到set中
            }
            n = sum;//这一轮的sum是下一轮要进行每位平方和计算的n
        }
    }
};

时间复杂度: O(logn)
在次循环中的每次迭代,都会将 n 的位数减小一些。当 n 的位数为 k 时,经过 k 轮次循环后,n 就会变成 0 退出次循环。而主循环的循环次数取决于输入进来的数 n ,无法判断主循环次数,所以整体的时间复杂度可以表示为 O(logn)。

空间复杂度: O(logn)
unordered_set 变量 set 的空间复杂度是 O(logn)。
整数变量 sum 的空间复杂度是 O(1),因为它只占用了常数级的空间,相对于对数级忽略不计。

新手可能不理解的代码(其实是我自己学习到的新知识)

1. 怎么判断一个数是否在set存在

if(set.find(sum) != set.end())//判断此次sum是否重复出现

其实在349. 两个数组的交集这道题中也用到了这个条件判断语句,这里我针对这道题再解释一遍,也可以去看349这道题加深巩固一下理解。

这个条件语句是在检查 sum 是否存在于 set 这个无序集合(unordered set)中。逐步解释:

  1. set.find(num): 这个部分调用了 find 函数来在 set 中查找 sum。如果 sum 存在于 set 中,find 函数会返回指向 sum 的迭代器;如果不存在,它将返回 set.end(),即指向集合末尾的迭代器。

  2. set.end(): 这是集合的末尾迭代器,表示找不到指定元素的情况。

  3. 所以,set.find(sum) != set.end() 表达的意思是,如果 sum 存在于 set 中,条件成立,执行相应的操作。

set.begin()和set.end()这两个函数在利用已知数组创建新的集合(作用是利用集合的元素不可重复性来去除数组中重复的元素)也经常用到,我们都要熟悉一下运用方法,这里我举一个例子。

int array[] = {1, 2, 3, 2, 2, 4, 3, 5};
unordered_set<int> nums_set(array.begin(), array.end());//将array转换为set

这行代码创建了一个名为 nums_set 的无序集合(unordered_set),并使用 array 容器的迭代器范围(array.begin() 到 array.end())对其进行初始化。这种初始化方法允许直接将一个容器的元素范围传递给另一个容器或集合,从而方便地创建相同或相似(元素不可重复)的容器。

结尾碎碎念
“这次的算法解析只是冰山一角,未来我将持续分享更多有趣的算法问题,并提供更深入的解析。如果你对这个系列感兴趣,不要错过即将到来的更新!点赞、关注、收藏,如果有不同的解法欢迎留下你的评论,你们的支持就是我更新的最大动力。让我们一起探索更多算法的奇妙世界,这不仅是为了迎接面试挑战,更是为了成为在编程领域中游刃有余的专家。感谢大家的支持,期待未来更多的相遇和共同成长!”

  • 16
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值