Guide contents

Lesson 231 of 250

202. Happy Number

NeetCode: Happy Number · LeetCode: 202. Happy Number · Difficulty: Easy

Start with a positive integer n and repeatedly replace it by the sum of the squares of its digits. n is happy if this process reaches 1; otherwise it loops forever in a cycle that does not contain 1. Return whether n is happy.

Example

Text
Input:  n = 19    Output: true    (19 -> 82 -> 68 -> 100 -> 1)
Input:  n = 2     Output: false   (2 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 ...)

Brute force: remember every value seen

The sequence either reaches 1 or repeats a value. Keep a HashSet of everything seen; set.add(x) returns false when x is already present, so a failed add means the sequence is in a cycle and n is not happy. The sequence cannot grow without bound: a number with d digits maps to at most 81 * d, which is smaller than the number itself once it has more than three digits, so the sequence must eventually repeat or reach 1. Even Integer.MAX_VALUE (10 digits) maps to a value of at most 810, so the sum never overflows int.

Java
import java.util.HashSet;
import java.util.Set;

class Solution {
    private int next(int n) {
        int sum = 0;
        while (n > 0) {
            int d = n % 10;
            sum += d * d;
            n /= 10;
        }
        return sum;
    }

    public boolean isHappy(int n) {
        Set<Integer> seen = new HashSet<>();
        while (n != 1) {
            if (!seen.add(n)) {
                return false;
            }
            n = next(n);
        }
        return true;
    }
}

public class Main {
    public static void main(String[] args) {
        Solution s = new Solution();
        System.out.println(s.isHappy(19));
        System.out.println(s.isHappy(2));
        System.out.println(s.isHappy(1));
        System.out.println(s.isHappy(Integer.MAX_VALUE));
    }
}
Output
true
false
true
false

Time: roughly O(log n): after the first step the value is small (at most a few hundred), so the remaining walk has a bounded length. Space: O(1) in practice for the same reason, but the set is still extra memory.

Optimal: Floyd's fast and slow pointers

Treat the sequence as a linked list where each value points to its successor. Floyd's algorithm detects the cycle without storing values: move slow one step and fast two steps per round. If there is a cycle, they meet inside it. If fast reaches 1 first, the number is happy, since 1 maps to itself.

Java
class Solution {
    private int next(int n) {
        int sum = 0;
        while (n > 0) {
            int d = n % 10;
            sum += d * d;
            n /= 10;
        }
        return sum;
    }

    public boolean isHappy(int n) {
        int slow = n;
        int fast = next(n);
        while (fast != 1 && slow != fast) {
            slow = next(slow);
            fast = next(next(fast));
        }
        return fast == 1;
    }
}

public class Main {
    public static void main(String[] args) {
        Solution s = new Solution();
        System.out.println(s.isHappy(19));
        System.out.println(s.isHappy(2));
        System.out.println(s.isHappy(1));
        System.out.println(s.isHappy(Integer.MAX_VALUE));
    }
}
Output
true
false
true
false

Time: roughly O(log n) (the digit sums dominate; the cycle length is bounded by a small constant). Space: O(1).

Both versions have the same running time; the second uses constant memory.