676 字
3 分钟
Leetcode->快乐数
题目:star:
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
- 如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
示例 1:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:
输入:n = 2
输出:false
提示:
1 <= n <= 231 - 1
解题:smiley:
①利用哈希集合检测循环
TIP 根据题目中的规则,重复获得下一个数字,最终会有可能出现三种情况:
- 最终得到1
- 最终进入循环
- 得到的值越来越大,最后趋近无穷大
可以列举每一位的最大数字的下一位来观察规律:
Digits Largest Next 1 9 81 2 99 162 3 999 243 4 9999 324 13 9999999999999 1053 由上表可得:
- 对于3位及以下的数字,要么会处于243以内的循环中,要么得到1
- 对于4位及以上的数字在每一步都会丢失一位,直到降为3位,所以最坏的情况就是可能会在243以下的所有数字循环,然后回到它已经到过的一个循环或者回到 1
所以我们就不用考虑第三种情况,只需要判断 是否等于1 和 是否已经进入过这个循环,因此,利用哈希集合
/**
* @param {number} n
* @return {boolean}
*/
let getNext = function (n) {
let total = 0
while (n > 0) {
let d = n % 10
total += d * d
n = Math.floor(n/10)
}
return total
}
var isHappy = function (n) {
let s = new Set()
while (n != 1 && !s.has(n)) {
s.add(n)
n = getNext(n)
}
return n == 1
};
②快慢指针
TIP 通过反复调用
getNext(n)
得到的链是一个隐式的链表。隐式意味着我们没有实际的链表节点和指针,但数据仍然形成链表结构。所以此题就转化成了和之前很相似的 判断链表是否有环 问题 定义快慢指针,快指针一次2步,慢指针一次1步,这样如果存在环(循环),两者一定会相遇
/**
* @param {number} n
* @return {boolean}
*/
let getNext = function (n) {
let total = 0
while (n > 0) {
let d = n % 10
total += d * d
n = Math.floor(n/10)
}
return total
}
var isHappy = function (n) {
let slow = n
let fast = getNext(n)
while (fast !=2 && fast != slow) {
slow = getNext(slow)
fast = getNext(getNext(fast))
}
return fast == 1
};
Leetcode->快乐数
https://blog.oceanh.top/posts/algorithm/快乐数/