「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战」。
题目描述
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。
题解1-Map方案
思路分析
题目中讲,输入有两种情况,无限循环 或者 变为1
我们可以分析,所有数字最大也就是 1 ~ 9,因此按此规则枚举出来的最大值的平方也就是 8^2 + 1^2,
可以分析出来,无限循环其实是有规则的,因此可以使用map来记录你已经计算出来的数据
每次计算出来的值有没有在map中现过
如果有重复数据,则此数无限循环
如果存在1,那么此数为快乐数
return false || true
代码实现
var isHappy = function (n) {
const mapper = new Map();
let newNum = n;
let sum = 0;
while (newNum || sum !== 1) {
if (newNum === 0 && sum !== 1) {
if (mapper.has(sum)) {
return false;
} else {
mapper.set(sum, true);
}
newNum = sum;
sum = 0;
}
sum = Number(sum) + Number(newNum % 10) * Number(newNum % 10);
newNum = Math.floor(newNum / 10);
}
return sum === 1;
};
题解2-链表思维描述
处理算法实际就是在锻炼代码思维,因此也会将链表思路分析在下文,可以提升大家的代码修养,并且这个解法也非常的有趣。
思路分析
我们先分析题目,每次将该数的结果输出在一个链表结构中,假设分别输入进去的数字为,19 、 2,那么我们可以得到如下数据结构
19: 19 —> 82 —> 68 —> 100 —> 1
2: 2 —> 4 —> 16 —> 37 —> 58 —> 89 —> 145 —> 42 —> 20 —> 4 —> 16 —> 37
这些数据组成了一个数据上的链表。
先分析存在1的情况,存在1的话,那么我们只需要将计算过的数据放在一个变量之中,判断变量为1,return true。
假设不存在1呢?
我们来分析数据的规则,按照第二个数据结构来推测,如果数据没有推算出来1,则个位数的平方和是按照某种规则来循环生成数据的。(可能存在某种数学公式或者数学上的专业语言,作者暂时不清楚,欢迎大神评论区指导)。
因此上面的数据结构,可以归并为链表运算算法中的一道经典题目,链表探环之前文章指路
链表探环处理中有一种经典的解决方案,快慢指针,因此我们就采用此思路来整理此题
大概代码结构
1、创建一个方法,功能是根据传入数据按照规则生成下一位数据。
2、采用快慢指针思路,两个变量,分别用于存储当前数据和下一个数据。
3、创建一个循环,循环中每次循环,快指针走一步,慢指针走两步
4、根据最终循环结果来判断,生成的数据是否循环(链表探环),最终返回对应值
代码实现
const isHappy = (num) => {
const getNextNum = (n) => {
const nextNum = 0;
while(n) {
curNum += (n % 10) * (n % 10);
n = Math.floor( n / 10);
}
return nextNum;
}
let startNum = n, nextNum = getNextNum(n);
do {
startNum = getNext(start);
nextNum = getNext(getNext(nextNum));
} while(startNum !== nextNum && nextNum !== 1);
return nextNum === 1;
}