Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Build confidence with an intuition-first walkthrough focused on hash map fundamentals.
Write an algorithm to determine if a number n is happy.
A happy number is a number defined by the following process:
Return true if n is a happy number, and false if not.
Example 1:
Input: n = 19 Output: true Explanation: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1
Example 2:
Input: n = 2 Output: false
Constraints:
1 <= n <= 231 - 1Problem summary: Write an algorithm to determine if a number n is happy. A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits. Repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy. Return true if n is a happy number, and false if not.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Math · Two Pointers
19
2
linked-list-cycle)add-digits)ugly-number)sum-of-digits-of-string-after-convert)minimum-addition-to-make-integer-beautiful)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #202: Happy Number
class Solution {
public boolean isHappy(int n) {
Set<Integer> vis = new HashSet<>();
while (n != 1 && !vis.contains(n)) {
vis.add(n);
int x = 0;
while (n != 0) {
x += (n % 10) * (n % 10);
n /= 10;
}
n = x;
}
return n == 1;
}
}
// Accepted solution for LeetCode #202: Happy Number
func isHappy(n int) bool {
vis := map[int]bool{}
for n != 1 && !vis[n] {
vis[n] = true
x := 0
for ; n > 0; n /= 10 {
x += (n % 10) * (n % 10)
}
n = x
}
return n == 1
}
# Accepted solution for LeetCode #202: Happy Number
class Solution:
def isHappy(self, n: int) -> bool:
vis = set()
while n != 1 and n not in vis:
vis.add(n)
x = 0
while n:
n, v = divmod(n, 10)
x += v * v
n = x
return n == 1
// Accepted solution for LeetCode #202: Happy Number
use std::collections::HashSet;
impl Solution {
fn get_next(mut n: i32) -> i32 {
let mut res = 0;
while n != 0 {
res += (n % 10).pow(2);
n /= 10;
}
res
}
pub fn is_happy(mut n: i32) -> bool {
let mut set = HashSet::new();
while n != 1 {
let next = Self::get_next(n);
if set.contains(&next) {
return false;
}
set.insert(next);
n = next;
}
true
}
}
// Accepted solution for LeetCode #202: Happy Number
function isHappy(n: number): boolean {
const getNext = (n: number) => {
let res = 0;
while (n !== 0) {
res += (n % 10) ** 2;
n = Math.floor(n / 10);
}
return res;
};
const set = new Set();
while (n !== 1) {
const next = getNext(n);
if (set.has(next)) {
return false;
}
set.add(next);
n = next;
}
return true;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair of elements. The outer loop picks one element, the inner loop scans the rest. For n elements that is n × (n−1)/2 comparisons = O(n²). No extra memory — just two loop variables.
Each pointer traverses the array at most once. With two pointers moving inward (or both moving right), the total number of steps is bounded by n. Each comparison is O(1), giving O(n) overall. No auxiliary data structures are needed — just two index variables.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.
Wrong move: Advancing both pointers shrinks the search space too aggressively and skips candidates.
Usually fails on: A valid pair can be skipped when only one side should move.
Fix: Move exactly one pointer per decision branch based on invariant.