求star

开源不易,喜欢请点个star吧

Ocean Han
676 字
3 分钟
Leetcode->快乐数
2022-06-21

题目: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
  • 最终进入循环
  • 得到的值越来越大,最后趋近无穷大

可以列举每一位的最大数字的下一位来观察规律:

DigitsLargestNext
1981
299162
3999243
49999324
1399999999999991053

由上表可得:

  • 对于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/快乐数/
作者
Ocean Han
发布于
2022-06-21
许可协议
CC BY-NC-SA 4.0
最后修改时间
2024-08-10 10:08:49