代码随想录刷题-哈希表-快乐数

文章介绍了如何判断一个数是否为快乐数,快乐数定义为经过数位平方和的迭代过程最终达到1。通过示例19的计算过程,展示了数字和可能出现的循环。解决方案是使用unordered_set存储中间结果,检测循环以避免无限循环,时间复杂度为O(logn),空间复杂度为O(k)。
摘要由CSDN通过智能技术生成

快乐数

本节对应代码随想录中:代码随想录,讲解视频:暂无

习题

题目链接: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

set 解法

刚开始看到题目后,一直纠结于题目中说的可能无限循环。拆分数字并判断和是否为1并不困难,但如果程序可能陷入无限循环,那一直找不到结果就会超时,但是和一直不为1,又无法确定后面的和是否会为1。

没有思路的时候可以输出下每个数的和,看看整个过程,代码如下

int n = 12;
for (int i = 0; i < 20; i++) {
    int sum = 0;
    while (n != 0) {
        sum += (n % 10) * (n % 10);
        n /= 10;
    }
    cout << sum << "#";
    n = sum;
}

每次会输出数字的和,共输出20次

当 n=12时,会输 5#25#29#85#89#145#42#20#4#16#37#58#89#145#42#20#4#16#37#58#,注意看数字出现了循环。#89#145#42#20#4#16#37#58# 从89开始就有了这一段循环。既然出现循环,说明当计算的和为89的时候,程序计算一段时间和后又会回到89。也就是说,如果一个数字出现了第二次,那么在这个数前面一定存在一段循环,那这个数字 n 一定不是快乐数,因此就可以用 unordered_set 来判断元素是否重复出现,若重复出现则可以返回 false,终止这个无限循环。

class Solution {
   public:
    bool isHappy(int n) {
        unordered_set<int> mySet;
        while (1) {
            int sum = 0;
            // 计算每个位置上的数字的平方和
            while (n != 0) {
                sum += (n % 10) * (n % 10);
                n /= 10;
            }
            // 和为1则说明是快乐数
            if (sum == 1) {
                return true;
            }
            // 如果set中存在sum,说明一定会陷入循环中,即不可能是快乐数
            if (mySet.count(sum)) {
                return false;
            }
            mySet.insert(sum);
            n = sum;    // 将sum赋值给n,继续计算数字n每个位置上的数字的平方和
        }
    }
};
  • 时间复杂度:O(logn)。查找给定数字的下一个值的成本为 O(logn)
  • 空间复杂度:O(k)。其中 k 为循环的次数,每次循环都会存入 unordered_set 中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值