题目定义
编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。 如果 n 是快乐数就返回 True ;不是,则返回 False 。
输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
来源:leetcode-cn.com/problems/ha…
这道题有两种解法:哈希值,快慢指针,数学法;这里主要介绍前两种解法;
哈希值解法
方法实现
- 初始化集合set, n加入set;
- 把n替换为每个位置上的数字的平方和, 并加入set;
- 重复这一过程直到新出现的数字等于1时返回true, 或新出现的数字已经存在set中时返回false;
代码如下:
var isHappy = function(n) {
let SquareSum = (x) => {
let sum = 0, cur;
while(x > 0) {
cur = x % 10;
sum += cur * cur;
x = (x - cur) / 10;
}
return sum;
}
let map = new Set();
map.add(n);
while(n !== 1) {
n = SquareSum(n);
if(map.has(n)) {
return false;
}
map.add(n);
}
return true;
};
复杂度分析
假设从n到1或无限循环重复的第一个数一共需要经过x步变换:
时间复杂度:O(x);
空间复杂度:O(x);
快慢指针解法
方法实现
该问题可以转换为链表是否有环的问题。把转换过程中的每一个数看作单链表的一个节点,将1看作单链表的最后一个元素,如果无法从能转换为1,说明链表中存在环。
- 初始化两个数slow和fast为n;
- 在slow和fast不相等的情况下,每次slow转换一次,fast转换两次;
- 当slow等于fast时,如果slow为1,则n是快乐数,反之则不是;
代码如下:
var isHappy = function(n) {
let SquareSum = (x) => {
let sum = 0, cur;
while(x > 0) {
cur = x % 10;
sum += cur * cur;
x = (x - cur) / 10;
}
return sum;
}
let fast = n, slow = n;
do{
slow = SquareSum(slow);
fast = SquareSum(fast);
fast = SquareSum(fast);
}while(fast !== slow);
return slow === 1;
};
复杂度分析
时间复杂度:O(logx);
空间复杂度:O(1);