This problem, commonly known as the Happy Number problem, is a classic cycle-detection challenge. In NeetCode, it is referred to as the Non-Cyclical Number problem.
The Problem Explained
A number is "non-cyclical" if, by repeatedly replacing it with the sum of the squares of its digits, you eventually reach the number 1. If you get stuck in a loop (a cycle) that never reaches 1, the number is cyclical (unhappy).
Example: 19
- (Stops at 1 → True)
Step 1: Creating the Helper Function
Before solving the main logic, we need a way to calculate the "sum of squares of digits."
In JavaScript, we can do this mathematically using the modulo operator (%) and Math.floor(). This is more efficient than converting the number to a string.
function getSumOfSquares(n) {
let sum = 0;
while (n > 0) {
let digit = n % 10; // Get the last digit (e.g., 19 % 10 = 9)
sum += digit * digit; // Square it and add to sum
n = Math.floor(n / 10); // Remove the last digit (e.g., 1.9 becomes 1)
}
return sum;
}Step 2: The Logic (Using a Hash Set)
To know if we are in an infinite loop, we need to keep track of every number we've already seen. If we see a number for the second time, we know we are stuck in a cycle.
The Strategy:
- Create a
Setto store visited numbers. - While the current number is not
1:- Check if the number is already in the
Set. If yes, returnfalse(cycle detected). - If not, add the number to the
Set. - Calculate the next number using our helper function.
- Check if the number is already in the
- If the loop ends because the number became
1, returntrue.
Step 3: The Complete JavaScript Solution
/**
* @param {number} n
* @return {boolean}
*/
var isHappy = function(n) {
const seen = new Set();
// Keep going until n is 1 (success) or we hit a number we've seen before (fail)
while (n !== 1 && !seen.has(n)) {
seen.add(n);
n = getSumOfSquares(n);
}
// If the loop stopped because n is 1, return true. Otherwise, false.
return n === 1;
};
function getSumOfSquares(num) {
let output = 0;
while (num > 0) {
let digit = num % 10;
output += digit * digit;
num = Math.floor(num / 10);
}
return output;
}Why does this work? (Understanding the Constraints)
You might wonder: Could the numbers just keep getting bigger forever?
Actually, no. For any number with many digits, the sum of the squares of its digits will eventually shrink down into a smaller range (usually under 243 for 3-digit numbers). Once the numbers are in that small range, they must either hit 1 or start repeating. Because the space of possible numbers is limited, a Set is a perfect tool to catch those repeats.
Alternative: Floyd's Cycle-Finding Algorithm
If you want to be extra fancy (and save memory), you can use the "Fast and Slow Pointer" approach (Tortoise and Hare).
- The Slow pointer calculates the next sum once.
- The Fast pointer calculates the next sum twice.
- If they ever meet at the same number (other than 1), there is a cycle!
This approach uses space because you don't need a Set to store every number you've seen.
Happy Number - Leetcode 202 - Python Neetcode
This video provides a visual walkthrough of the cycle detection logic using both a Hash Set and the more advanced Fast and Slow pointers.