今天是2020年4月30日,星期四。四月的最后一天啦,五月运气好好呦。
题目描述
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 True ;不是,则返回 False 。
示例:
输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
题目分析
在本题目中,需要理解的关键是「无限循环 但始终变不到1」,在这种情况中一定存在循环节,即当前的数字n如果在之前已经出现过,那么一定无法变到1,这种则可以返回false。
在Java中可以借助HashSet来进行计算结果的去重。若当前数字已经在HashSet中出现过,则返回false;否则加入HashSet,进行下一轮的去重。
另一种方法则使用快慢指针的方法,每个中间计算的值都可以认为是链表中的一个节点,如果最后不能为1,则一定存在循环。则使用快慢指针验证链表中是否存在环。
参考代码
- 借用HashSet
/**
* 依靠hashset来存储之前计算过的值,如果已经发现了之前出现过的值,肯定不能到1
*
* @param n
* @return
*/
public boolean isHappy(int n) {
if (n == 1) {
return true;
}
Set<Integer> set = new HashSet<>();
set.add(n);
return isHappy(n, set);
}
private boolean isHappy(int n, Set<Integer> set) {
if (n == 1) {
return true;
}
List<Integer> list = new ArrayList<>();
int tmp = n;
while (tmp != 0) {
list.add(tmp % 10);
tmp = tmp / 10;
}
int next = 0;
for (Integer integer : list) {
next += (integer * integer);
}
if (set.contains(next)) {
return false;
} else {
set.add(next);
return isHappy(next, set);
}
}
- 快慢指针
/**
* 使用快慢指针
* 每个中间计算的值都可以认为是链表中的一个节点,如果最后不能为1,则一定存在循环。
* 则使用快慢指针查找链表中是否存在换
*
* @param n
* @return
*/
public boolean isHappy2(int n) {
if (n == 1) {
return true;
}
int slow = n;
int fast = squareSum(n);
while (slow != fast) {
slow = squareSum(slow);
fast = squareSum(squareSum(fast));
}
return slow == 1;
}
private int squareSum(int n) {
int sum = 0;
while(n > 0){
int digit = n % 10;
sum += digit * digit;
n /= 10;
}
return sum;
}