1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public boolean isHappy(int n) {
Set<Integer> visited = new HashSet<>();
visited.add(n);
while (n != 1) {
n = convert(n);
if (visited.contains(n))
return false;
visited.add(n);
}
return true;
}

private int convert(int n) {
int ans = 0;
while (n != 0) {
int current = n % 10;
ans += current * current;
n /= 10;
}
return ans;
}
}

最直接的用set来记录都遇到了哪些数字, 如果遇到了之前遇到过的, 那就说明出现了cycle, 此时返回false即可, 如果一直没遇到并最后产生了1, 那么返回true.

时间复杂度: O(logn) 这是convert这个method的时间复杂度. n这个数字有多少digit组成? log以10为底n的对数个.
空间复杂度: O(logn)
具体分析见202题官方解答.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public boolean isHappy(int n) {
int slow = n, fast = convert(n);
while (fast != 1 && slow != fast) {
slow = convert(slow);
fast = convert(convert(fast));
}
return fast == 1;
}

private int convert(int n) {
int ans = 0;
while (n != 0) {
int current = n % 10;
ans += current * current;
n /= 10;
}
return ans;
}
}

有cycle那就是典型的slow, fast指针. 需要注意的是slow和fast在同一起跑线也好, fast比slow往后多一个也好. 如果有cycle, 二者是会碰面的. 但是如果要找到cycle出现的第一个节点, 那么fast需要和slow同一起跑线出发, 这样的话, 等到二者相遇然后把slow重新放到起跑线再让二者相遇的时候, 那时相遇的点才是cycle的第一个节点. 如果一开始fast在slow后一个位置出发, 那么这相当于slow和fast在slow位置前一个位置同时出发, 那么等slow和fast相遇并把slow重制到开头的时候, 当二者再相遇的时候就不是cycle的起始点了.

时间复杂度: O(logn)
空间复杂度: O(1) 没有使用额外的数据结构存储东西.