LeetCode202 快乐数
题目
刷完快乐数,感到快乐的成本又上升了 T.T
解题
解题思路见:快乐数
关键在于能不能看透判断快乐数的本质:每步计算结果是否会形成环路
输入满足
1
<
=
n
<
=
2
31
−
1
1 <= n <= 2^{31} - 1
1<=n<=231−1,最大是 10 位,而
81
∗
124
=
10044
,
81
∗
123
=
9963
81 * 124 = 10044,81 * 123 = 9963
81∗124=10044,81∗123=9963。所以 4 - 12 位数,一次运算后变为 3 位数,13 - 123 位数,一次运算后变为 4 位数,两次运算后变为 3 位数,而这些数的个数是大于 243 的,所以一定会形成循环,而只有 1 的各位数平方和是自己本身。
自此快乐数问题转变为了寻找环路的问题。
解题一:用集合检测循环
// javascript
var isHappy = function(n) {
let seen = new Set();
while (n !== 1 && seen.has(n) === false) {
seen.add(n);
n = getNext(n); // 不能在 n 前加 let
}
return n === 1;
};
var getNext = function(x) {
let sum = 0, cur = 0;
while (x !== 0) {
cur = x % 10;
sum += cur * cur;
x = parseInt(x / 10);
}
return sum;
};
解题二:快慢指针法
思路参考 LeetCode141 环形链表
fastRunner 要先走一步(或者用 do while 循环),不然根本进不了 while 循环。
// javascript
var isHappy = function(n) {
let slowRunner = n;
let fastRunner = getNext(n); // 先走一步
while (fastRunner !== 1 && fastRunner !== slowRunner) {
slowRunner = getNext(slowRunner);
fastRunner = getNext(getNext(fastRunner));
}
return fastRunner === 1;
};
var getNext = function(x) {
let sum = 0, cur = 0;
while (x !== 0) {
cur = x % 10;
sum += cur * cur;
x = parseInt(x / 10);
}
return sum;
};
解题三:数学
仅供娱乐:
// javascript
var isHappy = function(n) {
let cycle_members = new Set([4, 16, 37, 58, 89, 145, 42, 20]);
while (n !== 1 && cycle_members.has(n) === false) {
n = getNext(n);
}
return n === 1;
};
var getNext = function(x) {
let sum = 0, cur = 0;
while (x !== 0) {
cur = x % 10;
sum += cur * cur;
x = parseInt(x / 10);
}
return sum;
};