用JavaScript刷leetcode第202题-快乐数

341 阅读2分钟

前言

刚看到看到这个题的时候,我是非常不快乐的。
但是在以后的面试遇到这道题的时候,我想我会是非常快乐的。

一、题目描述

题目地址
git代码
快乐数定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。
  • 如果可以变为1,那么这个数就是快乐数。 如果 n 是快乐数就返回true;不是,则返回 false

二、解题思路

本质还是链表判环,根据链表唯一指向来做。不会链表判环的可以先看我的之前写的用JavaScript刷leetcode第141题-链表是否有环这篇文章。

  1. 把1当成尾节点,因为1的平方和始终为1,会一直指向本身
  2. 无论有环还是无环时返回f === 1,快慢指针相遇了,说明快指针已经至少走了环一圈了,走了一圈没得到1,有人可能会说直接返回false,但我这么写也没毛病,还可以节省后面无环结果为1的代码。
  3. 有人可能会说这个链表有没有可能没有尽头,其实并不会。因为他不会一直变大,也不会一直变小。

三、代码

列两种写法,仅仅只是代码精简度不一样,并不是第二种解法

1.常规写法

var isHappy = function(n) {
  let s = n;
  let f = n;

 while(f !== 1 && getSquareSum(f) !== 1) {
    s = getSquareSum(s);
    f = getSquareSum(getSquareSum(f));
    if(s === f) return false;
  }
  
  return true;
};

function getSquareSum(n) {
  let res = 0;
  while(n) {
    res += (n % 10) ** 2
    n = Math.floor(n / 10)
  }
  return res;
}

2.用return f === 1 的写法

var isHappy = function(n) {
  let s = n;
  let f = n;

 do{
    s = getSquareSum(s);
    f = getSquareSum(getSquareSum(f));
  } while(f !== 1 && f !== s) 
  
  return f === 1;
};

function getSquareSum(n) {
  let res = 0;
  while(n) {
    res += (n % 10) ** 2
    n = Math.floor(n / 10)
  }
  return res;
}