A non-cyclical number is an integer defined by the following algorithm:
1, or it loops infinitely in a cycle which does not include 1.1, then the number is a non-cyclical number.Given a positive integer n, return true if it is a non-cyclical number, otherwise return false.
Example 1:
Input: n = 100
Output: trueExplanation: 1² + 0² + 0² = 1
Example 2:
Input: n = 101
Output: falseExplanation:1² + 0² + 1² = 22² = 44² = 161² + 6² = 373² + 7² = 585² + 8² = 898² + 9² = 1451² + 4² + 5² = 424² + 2² = 202² + 0² = 4 (This number has already been seen)
Constraints:
1 <= n <= 1000
You should aim for a solution as good or better than O(logn) time and O(logn) space, where n is the given integer.
Create a helper function that returns the sum of the squares of a number's digits. Then, simulate the given process. If we reach 1, return true. However, we may get stuck in a cycle if a number is processed more than once. What data structure can be used to detect if a number has already been processed?
We can use a hash set to detect if a number has already been processed. At each step, we update n with the return value of the helper function. If the result is 1, we return true. If n is already in the set, we return false. Otherwise, we add n to the hash set and continue.
Before attempting this problem, you should be comfortable with:
A number is called happy if repeatedly replacing it with the sum of the squares of its digits eventually leads to 1.
While doing this process, only two things can happen:
1 → the number is happySo the key problem is cycle detection.
A simple and beginner-friendly way to detect a cycle is to:
1visit to store numbers we have already seen.n is not in visit:n to visitn with the sum of the squares of its digitsn becomes 1, return truen repeated:falseHelper Function (Sum of Squares)
To compute the next number:
output = 0n > 0:n % 10outputn //= 10outputclass Solution:
def isHappy(self, n: int) -> bool:
visit = set()
while n not in visit:
visit.add(n)
n = self.sumOfSquares(n)
if n == 1:
return True
return False
def sumOfSquares(self, n: int) -> int:
output = 0
while n:
digit = n % 10
digit = digit ** 2
output += digit
n = n // 10
return outputA number is happy if repeatedly replacing it with the sum of the squares of its digits eventually reaches 1.
Just like the hash set approach, the process can:
1 → happy numberInstead of storing all visited numbers, we can detect a cycle using the fast and slow pointers technique (also known as Floyd's cycle detection).
The idea:
n → sumOfSquares(n) like moving through a linked listslow moves one step at a timefast moves two steps at a timeslow and fast will eventually meet1, then the number is happyThis avoids extra memory and still reliably detects cycles.
slow = nfast = sumOfSquares(n)slow != fast:slow one step:slow = sumOfSquares(slow)fast two steps:fast = sumOfSquares(sumOfSquares(fast))fast == 1:1true1falseHelper Function (Sum of Squares)
To compute the next number:
output = 0n > 0:n % 10outputn //= 10outputclass Solution:
def isHappy(self, n: int) -> bool:
slow, fast = n, self.sumOfSquares(n)
while slow != fast:
fast = self.sumOfSquares(fast)
fast = self.sumOfSquares(fast)
slow = self.sumOfSquares(slow)
return True if fast == 1 else False
def sumOfSquares(self, n: int) -> int:
output = 0
while n:
digit = n % 10
digit = digit ** 2
output += digit
n = n // 10
return outputA number is happy if repeatedly replacing it with the sum of the squares of its digits eventually reaches 1.
Just like before, this process either:
1 → happy numberThis solution uses a different cycle detection method called Brent's Algorithm, which is another form of fast–slow pointer technique.
Key idea:
n → sumOfSquares(n)We keep track of:
slow → a checkpoint valuefast → the moving valuepower → how far we go before resetting slowlam → current distance since last resetIf fast ever equals slow, a cycle is detected.
slow = nfast = sumOfSquares(n)power = 1 (current block size)lam = 1 (steps taken in current block)slow != fast:power == lam:slow = fastpower *= 2lam = 0fast one step forward:fast = sumOfSquares(fast)lam by 1.fast == 1:1truefalseHelper Function (Sum of Squares)
To compute the next number:
output = 0n > 0:n % 10outputn //= 10outputclass Solution:
def isHappy(self, n: int) -> bool:
slow, fast = n, self.sumOfSquares(n)
power = lam = 1
while slow != fast:
if power == lam:
slow = fast
power *= 2
lam = 0
fast = self.sumOfSquares(fast)
lam += 1
return True if fast == 1 else False
def sumOfSquares(self, n: int) -> int:
output = 0
while n:
digit = n % 10
digit = digit ** 2
output += digit
n = n // 10
return outputForgetting to detect cycles causes the program to loop forever for non-happy numbers. Without a hash set or fast/slow pointers, numbers like 2 will endlessly cycle through the same values (2 → 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 → ...) without ever reaching 1.
Using the wrong operations to extract digits leads to incorrect sum calculations. A common mistake is forgetting integer division when removing the last digit (n = n // 10) or using string conversion inefficiently. Always use n % 10 to get the last digit and n // 10 to remove it.