返回介绍

solution / 0200-0299 / 0202.Happy Number / README

发布于 2024-06-17 01:04:03 字数 6310 浏览 0 评论 0 收藏 0

202. 快乐数

English Version

题目描述

编写一个算法来判断一个数 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

解法

方法一:哈希表 + 模拟

将每次转换后的数字存入哈希表,如果出现重复数字,说明进入了循环,不是快乐数。否则,如果转换后的数字为 $1$,说明是快乐数。

时间复杂度 $O(\log n)$,空间复杂度 $O(\log n)$。

class Solution:
  def isHappy(self, n: int) -> bool:
    vis = set()
    while n != 1 and n not in vis:
      vis.add(n)
      x = 0
      while n:
        n, v = divmod(n, 10)
        x += v * v
      n = x
    return n == 1
class Solution {
  public boolean isHappy(int n) {
    Set<Integer> vis = new HashSet<>();
    while (n != 1 && !vis.contains(n)) {
      vis.add(n);
      int x = 0;
      while (n != 0) {
        x += (n % 10) * (n % 10);
        n /= 10;
      }
      n = x;
    }
    return n == 1;
  }
}
class Solution {
public:
  bool isHappy(int n) {
    unordered_set<int> vis;
    while (n != 1 && !vis.count(n)) {
      vis.insert(n);
      int x = 0;
      for (; n; n /= 10) {
        x += (n % 10) * (n % 10);
      }
      n = x;
    }
    return n == 1;
  }
};
func isHappy(n int) bool {
  vis := map[int]bool{}
  for n != 1 && !vis[n] {
    vis[n] = true
    x := 0
    for ; n > 0; n /= 10 {
      x += (n % 10) * (n % 10)
    }
    n = x
  }
  return n == 1
}
function isHappy(n: number): boolean {
  const getNext = (n: number) => {
    let res = 0;
    while (n !== 0) {
      res += (n % 10) ** 2;
      n = Math.floor(n / 10);
    }
    return res;
  };
  const set = new Set();
  while (n !== 1) {
    const next = getNext(n);
    if (set.has(next)) {
      return false;
    }
    set.add(next);
    n = next;
  }
  return true;
}
use std::collections::HashSet;
impl Solution {
  fn get_next(mut n: i32) -> i32 {
    let mut res = 0;
    while n != 0 {
      res += (n % 10).pow(2);
      n /= 10;
    }
    res
  }

  pub fn is_happy(mut n: i32) -> bool {
    let mut set = HashSet::new();
    while n != 1 {
      let next = Self::get_next(n);
      if set.contains(&next) {
        return false;
      }
      set.insert(next);
      n = next;
    }
    true
  }
}
int getNext(int n) {
  int res = 0;
  while (n) {
    res += (n % 10) * (n % 10);
    n /= 10;
  }
  return res;
}

bool isHappy(int n) {
  int slow = n;
  int fast = getNext(n);
  while (slow != fast) {
    slow = getNext(slow);
    fast = getNext(getNext(fast));
  }
  return fast == 1;
}

方法二:快慢指针

与判断链表是否存在环原理一致。如果 $n$ 是快乐数,那么快指针最终会与慢指针相遇,且相遇时的数字为 $1$;否则,快指针最终会与慢指针相遇,且相遇时的数字不为 $1$。

因此,最后判断快慢指针相遇时的数字是否为 $1$ 即可。

时间复杂度 $O(\log n)$,空间复杂度 $O(1)$。

class Solution:
  def isHappy(self, n: int) -> bool:
    def next(x):
      y = 0
      while x:
        x, v = divmod(x, 10)
        y += v * v
      return y

    slow, fast = n, next(n)
    while slow != fast:
      slow, fast = next(slow), next(next(fast))
    return slow == 1
class Solution {
  public boolean isHappy(int n) {
    int slow = n, fast = next(n);
    while (slow != fast) {
      slow = next(slow);
      fast = next(next(fast));
    }
    return slow == 1;
  }

  private int next(int x) {
    int y = 0;
    for (; x > 0; x /= 10) {
      y += (x % 10) * (x % 10);
    }
    return y;
  }
}
class Solution {
public:
  bool isHappy(int n) {
    auto next = [](int x) {
      int y = 0;
      for (; x; x /= 10) {
        y += pow(x % 10, 2);
      }
      return y;
    };
    int slow = n, fast = next(n);
    while (slow != fast) {
      slow = next(slow);
      fast = next(next(fast));
    }
    return slow == 1;
  }
};
func isHappy(n int) bool {
  next := func(x int) (y int) {
    for ; x > 0; x /= 10 {
      y += (x % 10) * (x % 10)
    }
    return
  }
  slow, fast := n, next(n)
  for slow != fast {
    slow = next(slow)
    fast = next(next(fast))
  }
  return slow == 1
}
function isHappy(n: number): boolean {
  const getNext = (n: number) => {
    let res = 0;
    while (n !== 0) {
      res += (n % 10) ** 2;
      n = Math.floor(n / 10);
    }
    return res;
  };

  let slow = n;
  let fast = getNext(n);
  while (slow !== fast) {
    slow = getNext(slow);
    fast = getNext(getNext(fast));
  }
  return fast === 1;
}
impl Solution {
  pub fn is_happy(n: i32) -> bool {
    let get_next = |mut n: i32| {
      let mut res = 0;
      while n != 0 {
        res += (n % 10).pow(2);
        n /= 10;
      }
      res
    };
    let mut slow = n;
    let mut fast = get_next(n);
    while slow != fast {
      slow = get_next(slow);
      fast = get_next(get_next(fast));
    }
    slow == 1
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文