题目描述
编写一个算法来判断一个数 n 是不是快乐数。「快乐数」定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果 可以变为 1,那么这个数就是快乐数。
我的解法
思路
- 循环与终止条件怎么设置?因为按照题干中的流程会出现无限循环的情况
【没有想出来,不过这条规律应该需要推理才能获取,着重关注下别人方法中的推理过程】 - 过程中怎么获取到每个位置上的数字,以什么结构存储。
【这个要根据1中的条件选择最适合的方法】
更优解法
此部分转载于公众号代码随想录
思路
这道题目看上去貌似一道数学问题,其实并不是!
题目中说了会 「无限循环」
,那么也就是说「求和的过程中,sum会重复出现,这对解题很重要!」
而「当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。」
所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
判断sum是否重复出现就可以使用unordered_set,对应java中就是hashset
「还有一个难点就是求和的过程,如果对取数值各个位上的单数操作不熟悉的话,做这道题也会比较艰难。」
个人小结
原来不是个数学问题,不过还是有一点逻辑在的,那就是无限循环的话一定会重复,否则就不能称之为无限循环了,往极端想,把所有自然数都遍历一遍后就会重复了。
因为可以遍历到的范围是有上限的,所有这个范围内的自然数就有限的。
一个n位的数,按照题目中的方法,最大的结果是9²n,也就是81n
而当n=1,2时还可以扩大位数,但是当n>=3时位数就不会再增加了,所以是有限的。
说实话这点已经快想出来了,害…
对应Java代码
class Solution {
int getSum (int n) {
int sum = 0;
while(n != 0 ) {
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
public boolean isHappy(int n) {
Set<Integer> sumSet = new HashSet<>();
int sumRes = getSum(n);
while (sumRes != 1) {
if (sumSet.contains(sumRes)) { return false; }
sumSet.add(sumRes);
sumRes = getSum(sumRes);
}
return true;
}
}
复杂度分析
根据力扣官方题解,确定这个问题的时间复杂度对于一个「简单」级别的问题来说是一个挑战。如果您对这些问题还不熟悉,可以尝试只计算 getNext(n) 函数的时间复杂度。