leetcode-master/problems/0202.快乐数.md

197 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<p align="center">
<a href="https://mp.weixin.qq.com/s/RsdcQ9umo09R6cfnwXZlrQ"><img src="https://img.shields.io/badge/PDF下载-代码随想录-blueviolet" alt=""></a>
<a href="https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw"><img src="https://img.shields.io/badge/刷题-微信群-green" alt=""></a>
<a href="https://space.bilibili.com/525438321"><img src="https://img.shields.io/badge/B站-代码随想录-orange" alt=""></a>
<a href="https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ"><img src="https://img.shields.io/badge/知识星球-代码随想录-blue" alt=""></a>
</p>
<p align="center"><strong>欢迎大家<a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
> 该用set的时候还是得用set
# 第202题. 快乐数
https://leetcode-cn.com/problems/happy-number/
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1也可能是 无限循环 但始终变不到 1。如果 可以变为  1那么这个数就是快乐数。
如果 n 是快乐数就返回 True ;不是,则返回 False 。
**示例:**
输入19
输出true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
# 思路
这道题目看上去貌似一道数学问题,其实并不是!
题目中说了会 **无限循环**,那么也就是说**求和的过程中sum会重复出现这对解题很重要**
正如:[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/RSUANESA_tkhKhYe3ZR8Jg)中所说,**当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。**
所以这道题目使用哈希法来判断这个sum是否重复出现如果重复了就是return false 否则一直找到sum为1为止。
判断sum是否重复出现就可以使用unordered_set。
**还有一个难点就是求和的过程,如果对取数值各个位上的单数操作不熟悉的话,做这道题也会比较艰难。**
C++代码如下:
```C++
class Solution {
public:
// 取数值各个位上的单数之和
int getSum(int n) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> set;
while(1) {
int sum = getSum(n);
if (sum == 1) {
return true;
}
// 如果这个sum曾经出现过说明已经陷入了无限循环了立刻return false
if (set.find(sum) != set.end()) {
return false;
} else {
set.insert(sum);
}
n = sum;
}
}
};
```
# 其他语言版本
Java
```java
class Solution {
public boolean isHappy(int n) {
Set<Integer> record = new HashSet<>();
while (n != 1 && !record.contains(n)) {
record.add(n);
n = getNextNumber(n);
}
return n == 1;
}
private int getNextNumber(int n) {
int res = 0;
while (n > 0) {
int temp = n % 10;
res += temp * temp;
n = n / 10;
}
return res;
}
}
```
Python
```python
class Solution:
def isHappy(self, n: int) -> bool:
set_ = set()
while 1:
sum_ = self.getSum(n)
if sum_ == 1:
return True
#如果这个sum曾经出现过说明已经陷入了无限循环了立刻return false
if sum_ in set_:
return False
else:
set_.add(sum_)
n = sum_
#取数值各个位上的单数之和
def getSum(self, n):
sum_ = 0
while n > 0:
sum_ += (n%10) * (n%10)
n //= 10
return sum_
```
Go
```go
func isHappy(n int) bool {
m := make(map[int]bool)
for n != 1 && !m[n] {
n, m[n] = getSum(n), true
}
return n == 1
}
func getSum(n int) int {
sum := 0
for n > 0 {
sum += (n % 10) * (n % 10)
n = n / 10
}
return sum
}
```
javaScript:
```js
function getN(n) {
if (n == 1 || n == 0) return n;
let res = 0;
while (n) {
res += (n % 10) * (n % 10);
n = parseInt(n / 10);
}
return res;
}
var isHappy = function(n) {
const sumSet = new Set();
while (n != 1 && !sumSet.has(n)) {
sumSet.add(n);
n = getN(n);
}
return n == 1;
};
// 使用环形链表的思想 说明出现闭环 退出循环
var isHappy = function(n) {
if (getN(n) == 1) return true;
let a = getN(n), b = getN(getN(n));
// 如果 a === b
while (b !== 1 && getN(b) !== 1 && a !== b) {
a = getN(a);
b = getN(getN(b));
}
return b === 1 || getN(b) === 1 ;
};
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
* B站视频[代码随想录](https://space.bilibili.com/525438321)
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
<div align="center"><img src=../pics/公众号.png width=450 alt=> </img></div>