快乐数

力扣题目链接(opens new window)

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

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

如果 n 是快乐数就返回 True ;不是,则返回 False 。

示例:

输入:19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

初见思路

题意不难理解

步骤大致可以拆分成:

1、获取输入整数各位上的数

2、做平方后相加

3、重复上述过程

显然需要有一个循环计算的过程,那么结束条件是sum为1,但要是出现无限循环(sum一直不为1)的情况,那程序就卡死了

如何处理上述情况?

思路

本题的两个关键点:取各个数位上的单个数、循环结束条件

取各个数位上的单个数

先再次复习一下编程中的两种除法操作:取整取余(取模)

在c++中,

"/"是做取整数的除法,例如:19/10 = 1.9 = 1

"%"是做取除法但是取余数的值,例如:19%10 = 1余9 = 9

那么,可以先用10来和输入整数做取余运算来不断获取整数的个位数,然后通过取整运算将已经获取的数去除

如此循环到只剩下一位数,其再做除法得小数,经过取整后得0,此时循环结束

void getEechNum(int n) {
    int curNum;
    cout << "从个位开始的每个数为:" << endl;
    while (n) {//同时,以n作为循环结束条件
        curNum = n % 10;//获取当前个位上的数
        cout << curNum << endl;
        n /= 10;//去除已获取到的数
    }
}

int main() {
    getEechNum(156);
}

题中要求取到整数的每个单个数后做平方运算,因此用来取每个数的函数可以写成:

// 取数值各个位上的单数之和
int getSum(int n) {
    int sum = 0;
    while (n) {
        sum += (n % 10) * (n % 10);//直接在这里做平方运算
        n /= 10;
    }
    return sum;
}
循环结束条件

通过题目可知,“快乐数”的计算过程可能会出现无限循环的情况

例如,输入整数A,经过10次计算后sum = A

这就进入无限循环了,那么整数A也就不可能是快乐数

上述现象可以作为判断快乐数时循环结束的条件

具体处理上,我们可以让每次计算得到的sum保存到unordered_set中,一旦出现重复值(涉及判断重复值的,直接联想哈希表),即可作出判断。

代码

class Solution {
public:
    int getSum(int n){
        int sum = 0;
        while(n){
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
        //定义一个unordered_set
        unordered_set<int> set;
        //4、循环计算过程,知道找出快乐数或者陷入死循环
        while(1){
            //1、获取输入整数每各数位上的数的平方和
            int sum = getSum(n);
            //2、判断和是否为1
            if (sum == 1) {
                return true;
            }else if(set.find(sum) != set.end()){//如果sum值在set中出现过,则陷入循环
                return false;
            }else{
                set.insert(sum);
            }  
            //3、不为1则更新n值继续计算
            n = sum; //重复对sum进行上述运算 
        }
    
    }
};