Leetcode 202.快乐数
编写一个算法来判断一个数 n 是不是快乐数。
快乐数」定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。
示例 1:
输入:19
输出:true
解释:
12 + 92 = 82(这里的每个2代表平方的意思)
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:
输入:n = 2
输出:false
提示:
1 <= n <= 231 - 1
首先我们要知道如何计算这个快乐数,
我们需要提取出这个数字的每一位然后进行平方和
提取每一位数字的操作为
d = n % 10;
n /= 10;
简单说就是除10取余
比如19 % 10 商1余9 这样就取出了19中的9,1同样的道理
n /= 10的作用是为了取出这个数字的每一位的值,例如19 / 10 = 1,将19中的十位数1取了出来
最后将这俩个数的平方和相加
int d = n % 10;
n /= 10;
private int getNext(int n) {
int sum = 0;
while (n > 0) {
int d = n % 10;
n /= 10;
sum += d * d;
}
return sum;
}
接下来我们就要判断在这个循环可不可以这个数变成1;
我们需要将每次循环的数字存储起来,方便我们查看在这个循环中是不是出现了相同的循环数,如果出现了相同的循环数,且这个数不是1,那么说明在这个循环里会出现一个有序循环,不可能变成1;
但是我们不能将所有的循环数都存储起来,然后去判断,那样会耗费大量时间和空间,所以在这里我们用到了HashSet;
科普一下(和这道题关系不大)
在HashSet中每天添加一个数字,他都会判断在这里面有没有这个数,如果有这个数,直接返回,有兴趣可以看看源代码
/**
*Adds the specified element to this set if it is not already present.
* More formally, adds the specified element <tt>e</tt> to this set if
* this set contains no element <tt>e2</tt> such that
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*
* @param e element to be added to this set
* @return <tt>true</tt> if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
这句话的大概意思就是我上面所说的。
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
//在这里之所以会有!set.contains(n)这个条件是因为我需要
//一个跳出条件,不然在一个数字中存在循环的话这个方法会一直执行下去
while (n != 1 && !set.contains(n)) {
set.add(n);
//将添加在set中的数字继续进行getNext操作
n = getNext(n);
}
return n == 1;
}
//计算出n的每个位置上数字的平方,然后求和
private int getNext(int n) {
int sum = 0;
while (n > 0) {
int d = n % 10;
n /= 10;
sum += d * d;
}
return sum;
}
}
2.双指针(快慢指针)
在方法一中我们说道,如果不是快乐数,会出现一个有序循环,就像下图一样
这样我们就可以设置俩个指针,一个快指针一个慢指针;
快指针每次走俩个单位,慢指针走一个单位,
如果是快乐数(存在有序循环),那么这俩个指针一定会在某个地方相遇,
如果不存在快乐数,快指针一定比慢指针先到达数字1.
如果存在有序循环,俩指针一定会在那个环里的某个位置相遇。
class Solution {
public boolean isHappy(int n) {
int slow = n;
int fast = getNext(n);
//第一个条件是为了一目了然,为了判断是否为1
//第二个条件,判断是否相遇,如果相遇,则跳出循环
//注意:不存在slow 和 fast 都等于1 且相遇的情况,因为fast比slow快,一定比slow先到达数字1
while (fast != 1 && slow != fast) {
slow = getNext(slow);
fast = getNext(getNext(fast));
}
return fast == 1;
}
public int getNext(int n) {
int sum = 0;
while (n > 0) {
int d = n % 10;
n /= 10;
sum += d * d;
}
return sum;
}
}
如有错误,请指教!