【路飞】leetcode-202.快乐数

127 阅读2分钟

加油 第 3 练

202. 快乐数

题目描述:编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」定义为:

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

解题思路

  • 首先取出数字的每一位(独立拿出);
  • 循环替换数字为每一位数字的平方和;
  • 循环结束条件:
    • 结果为1则该数是快乐数,返回true;
    • 不为1则继续判断循环结果是否出现了重复结果(判断是否出现循环)
      • 出现重复,返回false;
      • 未出现更新数值,继续循环;

方法一:循环存储,判断结果(出现重复/1)

/**
 * @param {number} n
 * @return {boolean}
 */
var isHappy = function(n) {
    //取出数字的每一位
    function handleNum(n){
        let nums = [];
        while (n > 0) {
            nums.push(Math.floor(n % 10))
            n = Math.floor(n / 10)
        }
        return nums;
        //return n.toString().split("")
    }
    var resultArr = [];//保存每次的结果
    while (true) {
        const nums = handleNum(n);
        let sum = 0; //求和结果
        nums.map(item => Math.pow(item, 2)).forEach(v => sum += v);
        //sum = nums.reduce((a,b)=> a + Math.pow(item, 2) ,0)
        //是快乐数
        if (sum === 1) {
            return true;
        }
        //有重复结果
        if (resultArr.indexOf(sum) != -1) {
            return false;
        }
        resultArr.push(sum);
        n = sum;
    }
    
    或者 :
    resultArr = new Set();
    while (true) {
        const nums = handleNum(n);
        let sum = 0;
        nums.map(item => Math.pow(item, 2)).forEach(v => sum += v);
        if (sum === 1) {
            return true;
        }
        if (resultArr.has(sum)) {
            return false;
        }
        resultArr.add(sum);
        n = sum;
    }
    //...map同理
};

方法二:快慢指针

回想前一篇单链表中有环(说明有重复),与方法一判重方法不同

  • 如果快指针结果得到1,是快乐数,退出循环
  • 快慢指针相遇(重复),退出循环
var isHappy = function(n) {
    //下一个数字
    function nextN(n){
        return n
        .toString()
        .split("")
        .map((i) => i ** 2)
        .reduce((a, b) => a + b);
    }
    
  let slow = n;
  let fast = nextN(n);
  while (fast !== 1 && fast !== slow) {
    slow = getNext(slow);
    fast = getNext(getNext(fast));
  }
  return fast === 1;
};