Take a number, sum the squares of its digits, and repeat. If the process reaches 1, the number is happy. If it never reaches 1, the process cycles forever, and the number is unhappy.
The second case is the harder one. How do you stop if the number is not happy? You cannot run the process forever. Unhappy numbers always enter a cycle, and the reason is that the values stay bounded. The digit-square-sum of any number below 2^31 falls into a small range (the maximum for a 10-digit number is 9^2 * 10 = 810), so the sequence can only take finitely many values. By the pigeonhole principle, some value must repeat, which means the process is in an infinite loop.
The problem reduces to detecting whether the sequence reaches 1 or enters a cycle.
1 <= n <= 2^31 - 1. The input can be any positive 32-bit integer. After one iteration of digit-square-sum, even the largest value (2,147,483,647) maps to at most 810. From there the sequence stays inside the range [1, 810], so the number of distinct values, and therefore the work to detect a cycle, is bounded by a constant.Store every number the process produces. If the current number is 1, the number is happy. If the current number has appeared before, the sequence is in a cycle and the number is unhappy.
This is the same technique used to detect a cycle in a linked list with a visited set. It trades memory for a straightforward termination condition: the loop stops the first time a value repeats.
seen to store numbers we've encountered.n is not 1 and n is not in seen:n to seen.n with the sum of the squares of its digits.true if n equals 1, false otherwise.This detects cycles correctly, but the hash set grows with the number of distinct values. The next approach detects the same cycle using two pointers and constant extra space.
Instead of storing every number, use two pointers over the same sequence: a slow pointer that advances one step at a time, and a fast pointer that advances two steps at a time. If the sequence contains a cycle, the fast pointer eventually laps the slow pointer and they meet. If the sequence reaches 1, the fast pointer reaches 1 first, since 1 maps to itself.
The sequence of digit-square-sums behaves like a singly linked list: each number maps to exactly one next number, since the function is deterministic. If the sequence reaches 1, it stays at 1 forever. Otherwise the values are bounded by 810, so by the pigeonhole principle some value repeats and the sequence forms a cycle.
Floyd's algorithm relies on the fact that once both pointers are inside a cycle of length L, the gap between them closes by one each step, so they meet within L steps. The slow pointer cannot complete a full loop before that happens.
slow = n and fast = getNext(n).fast != 1 and slow != fast:slow one step: slow = getNext(slow).fast two steps: fast = getNext(getNext(fast)).true if fast == 1, false otherwise.Both approaches detect a cycle without knowing where it is. For this specific problem, the cycle is always the same one, which leads to a shorter solution.
Every unhappy number eventually reaches the cycle 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4. For numbers in the range [1, 810] this can be verified by direct enumeration, and since every input drops into that range after one step, it covers all 32-bit inputs. This is the only cycle the process can enter.
Because 4 lies on that cycle, reaching 4 is equivalent to entering the cycle. So the loop only needs to check two stopping conditions: did the value reach 1, or did it reach 4? Reaching 1 means happy, reaching 4 means unhappy. This removes the hash set and the second pointer, at the cost of relying on a fact specific to this problem rather than a general cycle-detection algorithm.
n is not 1 and n is not 4:n with the sum of the squares of its digits.true if n equals 1, false otherwise.