题目描述
大意就是:
给一个正整数,每次每个位置求平方和,如果最后每个位置的平方和为1,就判断为快乐数,否则永远不为1,就不是快乐数。
分析一波
首先看到这个题目,仔细想想感觉跟链表是否有环思路有点类似。是快乐数的话,就是有环了。
思路
思路:
利用快慢指针的方法,让p,q分别走一步,两步,
如果两者没有相遇(重点:相遇就证明有环,在相遇之前值都没有为1,那么就永远不可能为1,因为相遇后数字一直是环里的就是之前走过的数字)
并且q不等于1(其实代码里判断其中一个是否等于1就可以,因为相遇了两个肯定是相等的,这里最终判断走的快的那个q因为走的数字多,用这判断最佳),
就一直走,直到pq相遇以及q值为1。
为什么要用这种快慢指针的方式,判断是否有环?
因为:
相遇就证明有环,在相遇之前值都没有为1,那么就永远不可能为1,因为相遇后数字一直是环里的就是之前走过的数字一直循环。
实践,上代码分析
/**
* @param {number} n
* @return {boolean}
*/
var isHappy = function(n) {
if(!n) return false;
var club=(num)=>{
let result=0;
while(num){
//Math.pow这个是求底数的几次方,Math.floor是向下取整。%/10是取最后一位数,而/10是取除过末尾数的值。
result+=Math.pow(num%10,2);
num=Math.floor(num/10);
}
return result;
}
let p=n,q=club(n);
while(q!==1&&p!==q){
p=club(p);
q=club(club(q))
}
return q===1
};
分析
同样没有n也就是传进来的是一个空数,就直接返回false然后退出;
先定义了一个club方法,这里面主要做求传进来数每个位置上的平方和的;
club方法里面先定义一个变量result为0,是指平方和的;
while去循环传进来的值num, Math.pow这个是求底数的几次方,Math.floor是向下取整。%/10是取最后一位数,而/10是取除过末尾数的值。求完平方和之后,把result值返回;
接下来看club方法下面的:
定义一个变量p让它等于传进来的值n,然后再定义一个变量q,让q等于club方法调用一次后并返回的值,这里面传入了n。
同样使用循环去走这个链表,如果平方和值不为1,就一直往下走,让p接住club调用后返回的平方和的值,因为p是慢指针只走一步,所以就只电泳了一次;
但因为q是快指针,所以这里直接求了2次平方和;
最后判断q是否等于1,是的话就是快乐数,不是就返回false;
代码里的注意点
注意点:
这里的x%10就是取的数字的最后一位数字,比如130%10=0,
而x/=10则是取得是除过最后一位前几位的数字,很巧妙,比如130/10=13,
上面的方法如此循环,就可一次计算130各位置的平方数值和。
%10就是把最后一位数取出来,/10就是把最后一位数干掉。