🧠
Mathematical Insight with Known Cycle Detection
💡 This approach uses the known fact that all unhappy numbers eventually enter a fixed cycle. It avoids cycle detection by checking membership in this cycle.
Intuition
If the number becomes 1, it's happy. Otherwise, if it reaches any number in the known unhappy cycle {4,16,37,58,89,145,42,20}, it is not happy.
Algorithm
- Define a set of known unhappy cycle numbers.
- While n is not 1 and not in the unhappy set:
- Replace n with the sum of squares of its digits.
- Return true if n is 1, else false.
💡 The challenge is knowing the unhappy cycle beforehand and trusting this mathematical fact.
def isHappy(n: int) -> bool:
unhappy_cycle = {4, 16, 37, 58, 89, 145, 42, 20}
def digit_square_sum(num: int) -> int:
total = 0
while num > 0:
digit = num % 10
total += digit * digit
num //= 10
return total
while n != 1 and n not in unhappy_cycle:
n = digit_square_sum(n)
return n == 1
# Driver code
if __name__ == '__main__':
test_cases = [19, 2, 7, 1]
for num in test_cases:
print(f"Is {num} a happy number? {isHappy(num)}")
Line Notes
unhappy_cycle = {4, 16, 37, 58, 89, 145, 42, 20}Known cycle numbers where unhappy numbers get stuck.
while n != 1 and n not in unhappy_cycle:Loop until happy or known unhappy cycle detected.
n = digit_square_sum(n)Update n to sum of squares of digits.
return n == 1Return true if happy, false otherwise.
import java.util.Set;
import java.util.HashSet;
public class HappyNumber {
private static final Set<Integer> unhappyCycle = new HashSet<>();
static {
unhappyCycle.add(4); unhappyCycle.add(16); unhappyCycle.add(37); unhappyCycle.add(58);
unhappyCycle.add(89); unhappyCycle.add(145); unhappyCycle.add(42); unhappyCycle.add(20);
}
public static boolean isHappy(int n) {
while (n != 1 && !unhappyCycle.contains(n)) {
n = digitSquareSum(n);
}
return n == 1;
}
private static int digitSquareSum(int num) {
int total = 0;
while (num > 0) {
int digit = num % 10;
total += digit * digit;
num /= 10;
}
return total;
}
public static void main(String[] args) {
int[] testCases = {19, 2, 7, 1};
for (int num : testCases) {
System.out.println("Is " + num + " a happy number? " + isHappy(num));
}
}
}
Line Notes
private static final Set<Integer> unhappyCycle = new HashSet<>();Stores known unhappy cycle numbers.
while (n != 1 && !unhappyCycle.contains(n)) {Loop until happy or known unhappy cycle detected.
n = digitSquareSum(n);Update n to sum of squares of digits.
return n == 1;Return true if happy, false otherwise.
#include <iostream>
#include <unordered_set>
using namespace std;
bool isHappy(int n) {
static unordered_set<int> unhappyCycle = {4,16,37,58,89,145,42,20};
auto digitSquareSum = [](int num) {
int total = 0;
while (num > 0) {
int digit = num % 10;
total += digit * digit;
num /= 10;
}
return total;
};
while (n != 1 && unhappyCycle.find(n) == unhappyCycle.end()) {
n = digitSquareSum(n);
}
return n == 1;
}
int main() {
int testCases[] = {19, 2, 7, 1};
for (int num : testCases) {
cout << "Is " << num << " a happy number? " << (isHappy(num) ? "true" : "false") << endl;
}
return 0;
}
Line Notes
static unordered_set<int> unhappyCycle = {4,16,37,58,89,145,42,20};Known unhappy cycle stored statically for efficiency.
while (n != 1 && unhappyCycle.find(n) == unhappyCycle.end()) {Loop until happy or known unhappy cycle detected.
n = digitSquareSum(n);Update n to sum of squares of digits.
return n == 1;Return true if happy, false otherwise.
const unhappyCycle = new Set([4,16,37,58,89,145,42,20]);
function digitSquareSum(num) {
let total = 0;
while (num > 0) {
let digit = num % 10;
total += digit * digit;
num = Math.floor(num / 10);
}
return total;
}
function isHappy(n) {
while (n !== 1 && !unhappyCycle.has(n)) {
n = digitSquareSum(n);
}
return n === 1;
}
// Test cases
[19, 2, 7, 1].forEach(num => {
console.log(`Is ${num} a happy number? ${isHappy(num)}`);
});
Line Notes
const unhappyCycle = new Set([4,16,37,58,89,145,42,20]);Known unhappy cycle numbers stored in a set.
while (n !== 1 && !unhappyCycle.has(n)) {Loop until happy or known unhappy cycle detected.
n = digitSquareSum(n);Update n to sum of squares of digits.
return n === 1;Return true if happy, false otherwise.
TimeO(k * log n) where k is number of iterations until 1 or cycle
SpaceO(1) constant space
Each iteration computes sum of squares of digits (O(log n)) and checks membership in a small fixed set.
💡 This approach is very fast and memory efficient because the unhappy cycle is small and known.
Interview Verdict: Accepted
This approach is optimal and elegant but requires prior knowledge of the unhappy cycle.