Intuition
Repeatedly replace n by the sum of the squares of its digits. If you ever reach 1 it's happy; if you revisit a number you've seen before, you're in a cycle that never hits 1, so it's not.
Explanation
Idea
The process 'replace n by the sum of the squares of its digits' either reaches 1 (happy) or enters a cycle (unhappy). The only way to detect an endless loop is to notice we've returned to a number we already produced. A seen set records every value we visit; the moment a value repeats, we're cycling.
The values stay small (any number's digit-square-sum drops well below 1000 quickly), so the set never grows large.
Algorithm
- Keep a
seenset. - While
n != 1andnis not already inseen:- Add
ntoseen. - Replace
nwith the sum of the squares of its digits.
- Add
- Return
trueif the loop ended becausen == 1, elsefalse(we hit a repeat).
Worked example: n = 19
| n | digit squares | next n |
|---|---|---|
| 19 | 1² + 9² = 1 + 81 | 82 |
| 82 | 8² + 2² = 64 + 4 | 68 |
| 68 | 6² + 8² = 36 + 64 | 100 |
| 100 | 1² + 0² + 0² | 1 |
Reached 1 → 19 is happy → true.
An unhappy number like 2 cycles 2→4→16→37→58→89→145→42→20→4… and revisits 4, so the seen-set catches the loop and we return false.
Complexity
- Time: O(log n) per step with a bounded number of steps → effectively O(log n).
- Space: O(log n) for the seen set (bounded, since values stay small).
Implementation
import java.util.HashSet;
import java.util.Set;
class Solution {
public boolean isHappy(int n) {
Set<Integer> seen = new HashSet<>();
while (n != 1 && !seen.contains(n)) {
seen.add(n);
n = next(n);
}
return n == 1;
}
private int next(int n) {
int sum = 0;
while (n > 0) {
int d = n % 10;
sum += d * d;
n /= 10;
}
return sum;
}
}