leetcode 202-快乐数

405 阅读2分钟

题目定义        

        编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。 如果 n 是快乐数就返回 True ;不是,则返回 False 。  

输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

来源:leetcode-cn.com/problems/ha…

这道题有两种解法:哈希值,快慢指针,数学法;这里主要介绍前两种解法;

哈希值解法

方法实现

  • 初始化集合set, n加入set;
  • 把n替换为每个位置上的数字的平方和, 并加入set;
  • 重复这一过程直到新出现的数字等于1时返回true, 或新出现的数字已经存在set中时返回false;

代码如下:

var isHappy = function(n) {
  let SquareSum = (x) => {
    let sum = 0, cur;
    while(x > 0) {
      cur = x % 10;
      sum += cur * cur;
      x = (x - cur) / 10;
    }
    return sum;
  }
  let map = new Set();
  map.add(n);
  while(n !== 1) {
    n = SquareSum(n);
    if(map.has(n)) {
      return false;
    }
    map.add(n);
  }
  return true;
};

复杂度分析

假设从n到1或无限循环重复的第一个数一共需要经过x步变换:
时间复杂度:O(x);
空间复杂度:O(x);

快慢指针解法

方法实现

      该问题可以转换为链表是否有环的问题。把转换过程中的每一个数看作单链表的一个节点,将1看作单链表的最后一个元素,如果无法从能转换为1,说明链表中存在环。

  • 初始化两个数slow和fast为n;
  • 在slow和fast不相等的情况下,每次slow转换一次,fast转换两次;
  • 当slow等于fast时,如果slow为1,则n是快乐数,反之则不是;

代码如下:

var isHappy = function(n) {
    let SquareSum = (x) => {
        let sum = 0, cur;
        while(x > 0) {
            cur = x % 10;
            sum += cur * cur;
            x = (x - cur) / 10;
        }
        return sum;
    }
    let fast = n, slow = n;
    do{
        slow = SquareSum(slow);
        fast = SquareSum(fast);
        fast = SquareSum(fast);
    }while(fast !== slow);
    return slow === 1;
};

复杂度分析

时间复杂度:O(logx);
空间复杂度:O(1);