1. 问题描述:
编写一个算法来判断一个数是不是“快乐数”。
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
示例:
输入: 19
输出: true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/happy-number
2. 思路分析:
① 其实题目还是比较好理解,根据题目可以知道将输入的数字经过若干次的变换之后看是否等于1,其实对于这道题目来说判断是快乐数很简单,直接使用模拟的方法计算出等于1直接返回true即可,关键是判断不是快乐数的情况,不是快乐数的情况下会陷入死循环所以不能够使用模拟的方法来判断不是快乐数,否则有的不是快乐数但是会一直在循环中,即陷入了死循环之中,我一开始是使用模拟的方法但是后面发现提交上去无法判断不是快乐数的情况果断放弃这个思路
② 可以使用下面的两种方法来判断,一是使用较多人使用快慢指针的方法来进行判断,为什么要使用快慢指针呢?快慢指针是快指针走两步,慢指针走一步,假如有环的话那么快慢指针一定会在某一个位置相遇的,所以快慢指针经常使用来判断链表中是否存在环的情况,假如没有环快指针与慢指针是无法相遇在某个位置的,对于这道题目来说,快指针走两步,也就是计算两次平方和,慢指针走一次计算一次平方和,假如输入的数字是快乐数那么一定是不存在环的,无环的情况下快指针的结果最后一定是到达最终的数字1的(怎么样计算都是1),这个时候当慢指针追上快指针的时候一定会相遇在1这个时候判断循环退出之后两个相遇的位置是否是1即可判断是快乐数
当不是快乐数的时候快慢指针也会相遇,因为怎么样平方计算都不会到达1,因为这中间存在着重复的数字而且是永远到达不了1的,所以存在环两者一定会在某一个位置上相遇并且相遇的位置一定不是1,所以可以判断不是快乐数
③ 除了使用快慢指针,对于上面的分析之后我们知道,为什么不是快乐数呢因为中间的计算过程中遇到了重复的数字,而且不等于1所以是永远到达不了1的,这个时候使用set来来判断是否存在重复元素即可,假如出现了重复数字不等于1这个时候一定不是快乐数,假如是快乐数一定会最终等于1的所以两种情况都可以判断
3. 代码如下:
① 快慢指针
import java.util.Scanner;
public class Solution {
public int make(int n) {
int sum = 0;
//计算n的各位数字的平方和
while(n > 0) {
int bit = n % 10;
sum += bit * bit;
n = n / 10;
}
return sum;
}
public Boolean isHappy(int n) {
int slow = n, fast = n;
do{
//快指针走两步慢指针走一步
slow = make(slow);
fast = make(fast);
fast = make(fast);
}while(slow != fast);
return slow == 1;
}
}
② set判断是否存在重复元素
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Solution {
/*使用set来进行判断一旦中间过程出现了重复的数字且还没有到达1的时候这个时候肯定不是快乐数*/
public Boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
while (true){
int t = make(n);
if (t == 1) return true;
if (set.contains(t)) return false;
set.add(t);
/*将n为当前得到的平方数*/
n = t;
}
}
public int make(int n) {
/*计算n的各位数字上的平方和*/
int sum = 0;
while (n > 0){
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
}