加油 第 3 练
202. 快乐数
题目描述:编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果 可以变为 1,那么这个数就是快乐数。 如果 n 是快乐数就返回 true ;不是,则返回 false 。
解题思路
- 首先取出数字的每一位(独立拿出);
- 循环替换数字为每一位数字的平方和;
- 循环结束条件:
- 结果为1则该数是快乐数,返回true;
- 不为1则继续判断循环结果是否出现了重复结果(判断是否出现循环)
- 出现重复,返回false;
- 未出现更新数值,继续循环;
方法一:循环存储,判断结果(出现重复/1)
/**
* @param {number} n
* @return {boolean}
*/
var isHappy = function(n) {
//取出数字的每一位
function handleNum(n){
let nums = [];
while (n > 0) {
nums.push(Math.floor(n % 10))
n = Math.floor(n / 10)
}
return nums;
//return n.toString().split("")
}
var resultArr = [];//保存每次的结果
while (true) {
const nums = handleNum(n);
let sum = 0; //求和结果
nums.map(item => Math.pow(item, 2)).forEach(v => sum += v);
//sum = nums.reduce((a,b)=> a + Math.pow(item, 2) ,0)
//是快乐数
if (sum === 1) {
return true;
}
//有重复结果
if (resultArr.indexOf(sum) != -1) {
return false;
}
resultArr.push(sum);
n = sum;
}
或者 :
resultArr = new Set();
while (true) {
const nums = handleNum(n);
let sum = 0;
nums.map(item => Math.pow(item, 2)).forEach(v => sum += v);
if (sum === 1) {
return true;
}
if (resultArr.has(sum)) {
return false;
}
resultArr.add(sum);
n = sum;
}
//...map同理
};
方法二:快慢指针
回想前一篇单链表中有环(说明有重复),与方法一判重方法不同
- 如果快指针结果得到1,是快乐数,退出循环
- 快慢指针相遇(重复),退出循环
var isHappy = function(n) {
//下一个数字
function nextN(n){
return n
.toString()
.split("")
.map((i) => i ** 2)
.reduce((a, b) => a + b);
}
let slow = n;
let fast = nextN(n);
while (fast !== 1 && fast !== slow) {
slow = getNext(slow);
fast = getNext(getNext(fast));
}
return fast === 1;
};