方法:哈希法
为什么这么想:判断一个正整数是不是快乐数是要每一次将该数替换为它。一直重复,如果它变成1,说明是快乐数,如果它无限循环则不是快乐数。那我们怎么判断它是否无限循环了呢?很简单,就看它经过上面计算后是否与之前计算后的数相同,那就可以理解为快速判断一个元素是否出现集合里,因此用哈希法。接下来我们考虑用数组,set还是map。题目中说了1 <= n <= 2^31 - 1,可见数字太大,不适合数组。map的话要存入两个数据,而我们只需要存一个数据,因此用set。
思路:将一个正整数进行每个位置上的数字的平方和的计算,如果为1,返回true,不为1,看这个值之前是否存在,不存在添加到set,存在说明进入循环,返回false。
//改进前代码:两层while循环,时间复杂度高
class Solution {
public boolean isHappy(int n) {
ArrayList<Integer> list=new ArrayList<>();
HashSet<Integer> sumSet=new HashSet<>();
int n1=0;
int sum=0;
while(true)
{
//把n的每一位存入list集合
while(n!=0)
{
n1=n%10;
list.add(n1);
n=n/10;
}
//遍历list,求每个位置上的数字的平方和
for(int c:list)
sum=sum+c*c;
//清除list上的元素
list.clear();
//sum为1,是快乐数
if(sum==1)
return true;
//sum不为1
else
{
//set包含sum,说明无限循环,不是快乐数
if(sumSet.contains(sum))
return false;
//不包含
else
{
//sum存入set
sumSet.add(sum);
//改变n值
n=sum;
sum=0;
}
}
}
}
}
改进:再写一个方法专门处理每个位置上的数字平方和,这样就不会有两层while循环了。
//改进后代码
class Solution {
public boolean isHappy(int n) {
HashSet<Integer> sumSet=new HashSet<>();
int sum=0;
while(true)
{ //调用方法
sum=sumSquares(n);
//sum为1,是快乐数
if(sum==1)
return true;
//不为1
else
{
//进入循环,不是快乐数
if(sumSet.contains(sum))
return false;
//没有进入循环
else
{
//存入set
sumSet.add(sum);
//改变n的值
n=sum;
}
}
}
}
//计算n的每个位置上的数字的平方和
public int sumSquares(int n)
{
int sum=0;
int n1=0;
while(n!=0)
{
n1=n%10;
sum=sum+n1*n1;
n=n/10;
}
return sum;
}
}