「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」
题目
编写一个算法来判断一个数 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
解题
解题一:判断是否重复(HashSet)
思路
将每一次遍历到的数据存入 HashSet 中,判断是否有重复形成死循环,如果存在重复元素形成死循环,则返回 false,如果没有,最后结果一定为 true
代码
class Solution {
/**
* 返回正数每个位置上的数字的平方和
* @param value
* @return
*/
private int getNextValue(int value) {
int result = 0;
// 循环遍历数字的每个位置
while (value / 10 > 0) {
// 计算最低位的平方和 跟 result 进行累加
result += Math.pow(value % 10, 2);
// value除以10,计算高一位的平方和
value = value / 10;
}
// 最高位平方和
result += Math.pow(value % 10, 2);
return result;
}
public boolean isHappy(int n) {
Set<Integer> resultSet = new HashSet<>();
// 判断是否在 resultSet 中
while (!resultSet.contains(n)) {
// n == 1,满足快乐数的定义
if (n == 1) {
return true;
}
// 加入 resultSet 用户判断重复
resultSet.add(n);
// 获取下一个数进行判断
n = getNextValue(n);
}
return false;
}
}
总结
性能分析
- 执行耗时:1 ms,击败了 88.18% 的 Java 用户
- 内存消耗:35.5 MB,击败了 36.26% 的 Java 用户
解题一:双指针法(快慢指针)
思路
使用快慢指针思想,其中一个数每次进行一次计算,另一个数每次循环进行两次计算,判断这两个数是否相等,从而判断是否构成死循环,减少内存使用
代码
class Solution {
/**
* 返回正数每个位置上的数字的平方和
* @param value
* @return
*/
private int getNextValue(int value) {
int result = 0;
// 循环遍历数字的每个位置
while (value / 10 > 0) {
// 计算最低位的平方和 跟 result 进行累加
result += Math.pow(value % 10, 2);
// value除以10,计算高一位的平方和
value = value / 10;
}
// 最高位平方和
result += Math.pow(value % 10, 2);
// 返回计算结果
return result;
}
public boolean isHappy(int n) {
int slow = getNextValue(n);
// 判断 n 和 n 转换一次后是否为快乐数,直接返回结果
if (n == 1 || slow == 1) {
return true;
}
int fast = getNextValue(getNextValue(n));
while (slow != fast) {
// 慢数:每次进行一次转换
slow = getNextValue(slow);
// 快数:每次进行两次转换
fast = getNextValue(getNextValue(fast));
// 其中一个等于 1,代表满足快乐数定义
if (slow == 1 || fast == 1) {
return true;
}
}
// slow == fast 代表形成死循环,无法变成快乐数
return false;
}
}
总结
性能分析
- 执行耗时:1 ms,击败了 88.18% 的 Java 用户
- 内存消耗:35.2 MB,击败了 86.97% 的 Java 用户