一、问题描述:
大家好呀,我是善于思考的编程麒,大家可以叫我麒麒或者xin麒也可以呀。
Category | Difficulty | Likes | Dislikes |
---|---|---|---|
algorithms | Easy (62.47%) | 868 | - |
airbnb
| twitter
| uber
编写一个算法来判断一个数 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
二、思路:
难点在于构建循环体,细节问题也需要考虑。
xin麒的主要思路是取出n的每一位数,对每一位数进行平方相加得到sum,再将sum重新赋予n使得不断循环上述过程,以使得n<10(因为无论n是什么数,最后一定出现小于10的数),如果n小于10,且n等于1或7那么就返回true,(至于为什么等于7时就可以返回true,可以看文章最后面),反之返回false.
前提引入:
- 每次内层循环使用ren变量保存n的每一位数;
- 使用sum变量来保存n的每一位数的平方和;
分析过程:
- 首先这类题目一定先构造核心的循环体结构(xin麒一般先取核心,然后再逐步完善的):当n>=10(内层循环条件)满足时,进入循环;
-
- 使用ren保存n的每一位数
int ren = n % 10;
- 再使用sum来累加每一位数的平方:
sum += ren * ren;
- 每一次n都需要被削掉一位:
n /= 10;
- 因为内层循环退出后,此时的n的值为n开始最高位的值,sum还没有加上该最高位的平方,于是先让sum加上
n*n
,再让sum赋予n;
- 使用ren保存n的每一位数
-
- 外层循环的判断题解是true,外层循环结构体里有一个判断:为了判断每次内层循环处理后的n是否是小于10(如果小于10,而且等于1或7,那么返回true;如果小于10,不等于1或7,返回false)
三、题解:
麒麒一开始是使用普通思路来做的,但是出现了bug,于是就使用集合来做的,但是改用集合来做并没有beat100%,于是再次回到普通思路才beat100%,麒麒昨天优化接题思路以及优化代码的时间稍微长了点,太晚了,所以才今天发布啦。
xin麒的题解:
class Solution {
public boolean isHappy(int n) {
while (true) {
if(n < 10){
if(n == 1 || n == 7){
return true;
}else{
return false;
}
}
int sum = 0;
while (n >= 10) {
int ren = n % 10;
sum += ren * ren;
n /= 10;
}
sum += n * n;
n = sum;
}
}
}
运行:
四、最后
最终结果为1或7的数为什么都可以是快乐数呢?可以看一下:
这里是使用集合保存小于10的数,当小于10,就使用集合set来保存一下,如果被set接收的值是相同的,说明重复了,需要返回false.
class Solution {
public boolean isHappy(int n) {
HashSet<Integer> set = new HashSet<>();
while (true) {
if(n < 10){
if(n == 1){return true;}
if(!set.add(n)){
return false;
}
}
int sum = 0;
while (n >= 10) {
int ren = n % 10;
sum += ren * ren;
n /= 10;
}
sum += n * n;
n = sum;
}
}
}
运行:
于是xin麒在idea里面测试了一下:
五、哈希表的做法
使用哈希表来做,麒麒做不到beat100%,但是如果想的看xin麒还是很乐意分享的呀。