Happy Number

Easy Hash Maps

Problem

Given an integer n, return true if it is a happy number, and false otherwise. A happy number is defined by repeatedly replacing the number by the sum of the squares of its digits until it equals 1 or it loops endlessly in a cycle that does not include 1.

  • 1 ≤ n ≤ 2³¹ - 1

Example

Input: n = 19
Output: true

Starting with 19, the algorithm computes the sum of squares of digits: 1² + 9² = 1 + 81 = 82. Then for 82: 8² + 2² = 64 + 4 = 68. For 68: 6² + 8² = 36 + 64 = 100. For 100: 1² + 0² + 0² = 1. Since the sequence reaches 1, 19 is a happy number and the function returns true.

Approach

Straightforward Solution

A naive approach would repeatedly compute the sum of squares and check if the number is 1, but without cycle detection, this can lead to infinite loops for unhappy numbers.

Core Observation

The process of repeatedly replacing a number by the sum of the squares of its digits either eventually reaches 1 (happy number) or falls into a cycle that never reaches 1. Detecting this cycle is essential to avoid infinite loops.

Path to Optimal

The key recognition signals are 'detect cycle' and 'avoid infinite loops'. These indicate using a Hash Map or Set to track previously seen numbers. By storing each intermediate number, the algorithm can detect when a cycle occurs (a repeated number) and terminate early. This transforms the problem from potentially infinite iteration to a guaranteed termination with O(k) complexity, where k is the number of unique intermediate numbers.

Optimal Approach

Use a set to record all numbers encountered during the transformation. In each iteration, compute the sum of squares of digits. If the result is 1, return true. If the number has been seen before, a cycle exists, so return false. This approach guarantees termination and correctness.

Time

O(log n)

Each iteration reduces the number roughly to the sum of squares of its digits, which is bounded by a function of the number of digits. Since the number of digits is O(log n), and each number is unique until a cycle or 1 is found, the total iterations are bounded by a small constant related to digit sums.

Space

O(log n)

The visited set stores each unique intermediate number encountered. Since numbers are bounded by digit sums, the set size is proportional to the number of unique states, which is O(log n) in the number of digits.

Pattern Spotlight

Hash Maps (Cycle Detection via Visited Set)

When a process involves repeated transformations that may cycle, use a hash set to record visited states and detect cycles early, preventing infinite loops and ensuring termination.

Solution

1class Solution:
2 def isHappy(self, n: int) -> bool:
3 visit = set()
4
5 while n not in visit:
6 visit.add(n)
7 n = self.sumOfSquares(n)
8
9 if n == 1:
10 return True
11
12 return False
13
14 def sumOfSquares(self, n: int) -> int:
15 output = 0
16 while n:
17 digit = n % 10
18 digit = digit ** 2
19 output += digit
20 n = n // 10
21 return output

Step-by-Step Solution

1

Track Visited Numbers to Detect Cycles During Transformation

3visit = set()

Objective

To maintain a set of all numbers encountered to detect cycles and prevent infinite loops.

Key Insight

By storing each intermediate number in a set, the algorithm can quickly determine if the current number has appeared before, signaling a cycle. This prevents infinite repetition and ensures the algorithm terminates either by finding 1 or detecting a cycle.

Interview Quick-Check

Core Logic

Using a set to track visited numbers enables O(1) average-time cycle detection, which is essential for correctness and termination.

Common Pitfalls & Bugs

Failing to track visited numbers leads to infinite loops for unhappy numbers.

2

Iteratively Compute Sum of Squares and Check for Happiness or Cycle

5while n not in visit:
6 visit.add(n)
7 n = self.sumOfSquares(n)
9 if n == 1:
10 return True
12return False

Objective

To repeatedly transform the number by summing the squares of its digits and check for termination conditions.

Key Insight

The loop continues until the number is either 1 (happy) or repeats (cycle). Computing the sum of squares digit-by-digit ensures the transformation is correct. Checking for 1 immediately allows early termination for happy numbers.

Interview Quick-Check

Core Logic

The loop condition and checks ensure the algorithm terminates as soon as a happy number is found or a cycle is detected.

State & Boundaries

The loop continues while the current number has not been seen before, ensuring no repeated states.

Common Pitfalls & Bugs

Checking for 1 after updating the number is critical; missing this leads to incorrect results.

3

Calculate Sum of Squares of Digits for Current Number

14def sumOfSquares(self, n: int) -> int:
15 output = 0
16 while n:
17 digit = n % 10
18 digit = digit ** 2
19 output += digit
20 n = n // 10
21 return output

Objective

To compute the sum of the squares of each digit of the current number.

Key Insight

Breaking the number into digits using modulo and integer division allows precise calculation of the sum of squares. This transformation is the core operation that drives the state changes in the algorithm.

Interview Quick-Check

Core Logic

Digit extraction and squaring is done in a loop until the number is reduced to zero, ensuring all digits contribute to the sum.

Common Pitfalls & Bugs

Forgetting to update the number by integer division leads to infinite loops in digit processing.

Line Analysis

This solution has 3 Critical lines interviewers watch for.

Line 7 Critical
n = self.sumOfSquares(n)

Update the current number to the sum of the squares of its digits.

This line implements the key state transition by replacing the current number with the sum of squares of its digits, which is the defining operation of the happy number sequence.

Line 9 Critical
if n == 1:

Check if the current number is 1, indicating a happy number.

This check is critical because reaching 1 is the success condition; returning true here ensures correct and efficient termination.

Line 12 Critical
return False

Return false when a cycle is detected (number repeats without reaching 1).

Returning false here correctly identifies that the sequence has entered a cycle, proving the number is unhappy and preventing infinite loops.

Line 3 Core
visit = set()

Initialize a set to store numbers already seen during the transformation process.

This set is essential for cycle detection, allowing the algorithm to identify repeated states and prevent infinite loops.

Line 6 Core
visit.add(n)

Add the current number to the visited set.

Recording the current number marks it as seen, enabling future detection of cycles if the number reappears.

Line 21 Core
return output

Return the computed sum of squares of digits.

Returning this value provides the next state in the happy number sequence transformation.

Line 5 Core
while n not in visit:

Begin a loop that continues until the current number has been seen before.

This loop condition ensures the algorithm terminates either when a cycle is detected (number repeats) or when the number becomes 1 (happy number).

Line 10 Core
return True

Return true when the number is confirmed happy.

Returning immediately upon finding 1 prevents unnecessary further computation and signals success.

Line 16 Core
while n:

Extract the last digit of the number using modulo 10.

Modulo operation isolates the least significant digit, enabling digit-wise processing.

Line 17 Core
digit = n % 10

Square the extracted digit.

Squaring the digit is the core operation for the sum of squares transformation.

Line 18 Core
digit = digit ** 2

Add the squared digit to the output accumulator.

Accumulating the squared digits builds the transformed number for the next iteration.

Line 19 Core
output += digit

Remove the last digit from the number by integer division by 10.

Integer division truncates the processed digit, moving to the next digit in the next loop iteration.

Line 15 Standard
output = 0

Start a loop to process each digit of the number.

Iterating until the number is zero ensures all digits are processed exactly once.

Line 20 Standard
n = n // 10

Loop back to process the next digit until number is zero.

This loop ensures all digits are processed, completing the sum of squares calculation.

Line 14 Standard
def sumOfSquares(self, n: int) -> int:

Initialize the output sum for the sum of squares calculation.

This accumulator stores the sum of squared digits for the current number, resetting for each calculation.

Test Your Understanding

Why is it necessary to track previously seen numbers when determining if a number is happy?

Because without tracking, the process can enter an infinite cycle of numbers that never reach 1. Detecting repeated numbers indicates a cycle, allowing the algorithm to terminate and return false.

Related Problems

Hash Maps pattern

Don't just read it. Drill it.

Reconstruct Happy Number from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.

Unlock the Happy Number drill

or drill a free problem