[路飞]_LeetCode题202快乐数

221 阅读3分钟

题目描述

编写一个算法来判断一个数 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 <= 2^31- 1

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ha… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

根据题中描述的计算方法我们得知,一个数的最终结果有三种可能

  1. 最终会得到 1。

image.png 2. 最终会进入循环。

image.png 3. 值会越来越大,最后接近无穷大。 第三个情况比较难以检测和处理。我们怎么知道它会继续变大,而不是最终得到 11 呢?我们可以仔细想一想,每一位数的最大数字的下一位数是多少。

image.png 对于 33 位数的数字,它不可能大于 243243。这意味着它要么被困在 243243 以下的循环内,要么跌到 11。44 位或 44 位以上的数字在每一步都会丢失一位,直到降到 33 位为止。所以我们知道,最坏的情况下,算法可能会在 243243 以下的所有数字上循环,然后回到它已经到过的一个循环或者回到 11。但它不会无限期地进行下去,所以我们排除第三种选择。

即使在代码中你不需要处理第三种情况,你仍然需要理解为什么它永远不会发生,这样你就可以证明为什么你不处理它。

算法

算法分为两部分,我们需要设计和编写代码。

  1. 给一个数字 nn,它的下一个数字是什么?
  2. 按照一系列的数字来判断我们是否进入了一个循环。 第1部分我们按照题目的要求做数位分离,求平方和。 第2部分可以使用判断环形链表的方法判断下一个值是否形成循环。
  • 如果它不是环形链表应该返回true。
  • 如果它它是环形链表应该返回 false。

代码

 * @lc app=leetcode.cn id=202 lang=javascript
 *
 * [202] 快乐数
 */

// @lc code=start
/**
 * @param {number} n
 * @return {boolean}
 */
var isHappy = function(n) {
  //我们将1视作虚拟链表的null来处理
  let pre = n, cur = getNext(n);//pre慢指针,cue快指针
  //只要快慢指针不相遇且快指针不为零
  while(pre !== cur && cur !== 1){
    pre = getNext(pre);//慢指针移动一位
    cur = getNext(getNext(cur));//快指针移动两位
  }
  //循环结束如果是快指针走到1结束说明是快乐数返回true,
  //如果是快慢指针相等而结束循环则返回false
  return cur === 1;
};
//计算下一个得到的值
var getNext = function(n){
  let sum = 0;
  while(n){
    sum += (n%10)*(n%10);//计算个位数的平方求和
    n = Math.floor(n/10);//将n缩小10倍
  }
  return sum;
}
// @lc code=end