LC Patterns — Math & Number Theory

Per-pattern template: What it is → Intuition → Approach/template → Challenges & pitfalls → LC problems (max 3) → Worked examples.

The Master Insight (read before the patterns)

Math problems on LeetCode are anti-simulation problems: the naive answer is "loop and compute", and the intended answer is a piece of structure — a formula, an identity, a periodicity, an invariant — that collapses the loop. The interview is testing whether you look for structure before you reach for iteration.

Recognition trigger: huge bounds that make simulation impossible (n ≤ 10¹⁸, "return answer mod 10⁹+7"), digits/bases, "how many ways", divisibility/factors/primes, "without using ×/÷/pow", games with optimal play, or any statement that smells like a puzzle rather than a data-structure exercise. The phrase "mod 10⁹ + 7" is a flashing sign: the true answer is astronomically large ⇒ counting/combinatorics/fast-power, never enumeration.

Three habits separate strong candidates on math problems:

  1. Try small cases by hand first (n = 1..6) and look for the pattern/period/formula — say you're doing it; it's a method, not flailing.
  2. State the identity before coding it ("digit sums are ≡ the number mod 9", "divisors pair up around √n") — the identity is the solution; the code is transcription.
  3. Announce overflow/precision handling even in Python ("Python ints are arbitrary precision; in Java I'd need long here, and I'd mod after every multiply") — a free seniority signal, and some problems (7, 8) make 32-bit limits part of the spec.

§0The Toolbox & Universal Pitfalls

Identities and routines to have at your fingertips

import math
math.gcd(a, b); math.lcm(a, b)          # lcm(a,b) = a*b // gcd(a,b)
math.comb(n, k); math.isqrt(n)          # exact integer nCr and √ — no float drift
pow(a, e, m)                            # fast modular exponentiation, O(log e)
pow(a, -1, m)                           # modular inverse (m prime or gcd(a,m)=1)
divmod(n, 10)                           # (n // 10, n % 10) — the digit-peeling idiom
  • Euclid, two lines: while b: a, b = b, a % b — O(log min(a,b)). Bézout: ax + by = c solvable iff gcd(a,b) | c (this single fact is LC 365).
  • Sieve of Eratosthenes: O(n log log n); mark from i*i, step i, only for prime i ≤ √n.
  • Divisors pair around √n: enumerate i ≤ √n; each hit gives i and n // i. O(√n), and the perfect-square middle case appears once.
  • MOD discipline: MOD = 10**9 + 7; reduce after every + and *. Division under mod does not exist — multiply by the modular inverse (Fermat: pow(a, MOD-2, MOD) since MOD is prime). Subtraction: (a - b) % MOD — fine in Python, needs +MOD first in C++/Java.

Python-specific gotchas (these decide bugs, learn them cold)

  1. // floors toward −∞, C/Java truncate toward 0. -7 // 2 == -4 in Python, -7 / 2 == -3 in Java. LC 7 / 29 expect truncation → use int(a / b) or work with abs + sign. Same for %.
  2. Floats lie. 0.1 + 0.2 != 0.3; math.sqrt on big ints drifts. Use math.isqrt, integer cross-multiplication (compare a*d vs b*c, not a/b vs c/d), and Fraction only if desperate.
  3. Simulated 32-bit limits: INT_MAX = 2**31 - 1. Problems 7/8/29 require you to detect overflow that Python won't produce — check bounds explicitly and say so.

Universal pitfalls

  1. Simulating what has a formula — the failure mode this whole file exists to prevent. If bounds exceed ~10⁸ operations, a formula/period/doubling is mandatory.
  2. Modding too late or unevenly — one missed % MOD in a product chain is an overflow (other languages) or a wrong-answer-on-huge-case.
  3. Edge integers: 0, 1, negatives, INT_MIN (whose absolute value overflows in C/Java — the classic 29 trap), n = 1 in "count/kth" problems.
  4. Float equality anywhere — if you typed == between floats, redesign with integers.
  5. Not testing the formula — after deriving, verify against brute force for n ≤ 8 mentally. A formula off by one at n=2 fails 100% of cases.

1Digit Extraction & Reconstruction

What it is: Process a number digit-by-digit without converting to a string (or while pretending not to): reverse an integer, test a numeric palindrome, add one with carries. The atomic moves: peel with n % 10, shrink with n // 10, build with rev = rev * 10 + d.

Intuition: a decimal number is a stack of digits — % 10 pops, // 10 shrinks, *10 + d pushes onto a new number in reversed order. Reversal is therefore pop-everything-push-everything. Palindrome (9): reverse only half the number and compare (rev >= n stops the loop) — avoids any overflow question and handles odd lengths by rev // 10. Plus one (66): carries propagate only through trailing 9s.

Approach: loop while n: n, d = divmod(n, 10). For LC 7's overflow spec: check rev > (INT_MAX - d) // 10 before the push (predict overflow, don't detect it after). Negatives: strip the sign, restore at the end.

Challenges & pitfalls

Python's negative ///% silently corrupting digit peels (always work on abs); trailing zeros in palindromes (10 → false, but 0 → true); the half-reversal termination in 9 (rev >= n); resisting str(n)[::-1] — fine to mention, but the digit loop is what's examined.

LC 7 Reverse IntegerLC 9 Palindrome NumberLC 66 Plus One
Example 1: Reverse Integer (LC 7) — reverse x = 123 within 32-bit bounds.
  • Peel and rebuild: 123 → d=3, rev=3; 12 → d=2, rev=32; 1 → d=1, rev=321. Result 321. ✓
  • Overflow case x = 1534236469: reversing gives 9646324351, which exceeds INT_MAX = 2147483647. The pre-push check (rev > (INT_MAX − d)/10) catches this before the multiply → return 0 (per the 32-bit spec). The point of the exercise is predicting overflow, not detecting it after it happens.

2Manual Big-Number Arithmetic (schoolbook on strings)

What it is: Add or multiply numbers given as strings/arrays too large for fixed-width integers — reimplement the pencil-and-paper algorithms: right-to-left, per-position work, carry propagation.

Intuition: positional notation makes arithmetic local: position i of the result depends only on the input digits at/near i plus a carry. Addition: one zip from the right with a running carry. Multiplication (43): the key indexing fact — digit i × digit j lands in result positions i + j and i + j + 1 (from the right). Allocate len(a) + len(b) slots, accumulate raw products, then one carry-normalization pass.

Approach: addition template: two pointers from the ends, total = da + db + carry, emit total % base, carry = total // base, loop while i or j or carry, reverse at the end. Multiplication: res[i+j+1] += da*db double loop, then normalize carries right-to-left, strip leading zeros. Base 2 (67) is the same template with base = 2.

Challenges & pitfalls

forgetting the final carry (99 + 1); leading zeros after multiplication ("0" * "0""0", not ""); off-by-one in the i+j indexing (derive it on a 2×2 example); doing 43 via repeated addition (too slow); don't shortcut with int(s) in Python — legal syntax, instant fail on intent.

LC 415 Add StringsLC 67 Add BinaryLC 43 Multiply Strings
Example 1: Add Strings (LC 415)"456" + "77".
  • Add from the right with a carry:
    • 6 + 7 = 13 → digit 3, carry 1.
    • 5 + 7 + 1 = 13 → digit 3, carry 1.
    • 4 + 0 + 1 = 5 → digit 5, carry 0 (the shorter number contributes 0).
  • Collect digits and reverse → "533". ✓ The while i or j or carry loop is what handles the shorter operand and a final leftover carry (as in "99" + "1").

3GCD / LCM & Bézout's Identity

What it is: Problems whose hidden skeleton is the greatest common divisor: a common chunk size (strings, groups, decks), reachable water amounts with two jugs, synchronizing periodic events. Euclid's algorithm plus two facts — lcm = a·b/gcd and Bézout — cover all of them.

Intuition: gcd is "the largest unit both quantities are made of." String version (1071): if s + t == t + s the two strings are repetitions of one common block, and the answer's length is gcd(len(s), len(t)). Deck of cards (914): a valid group size must divide every count → feasible iff gcd(all counts) ≥ 2. Water jugs (365): every reachable amount is a Bézout combination ax + by, so the target is reachable iff target ≤ x + y and gcd(x, y) | target.

Approach: math.gcd / functools.reduce(gcd, counts) for the fold. Prove the string case both directions if asked: commuting concatenation ⇒ common period.

Challenges & pitfalls

recognizing gcd at all (the tell in 365: two step-sizes and a reachability question); the t ≤ x + y capacity cap in 365 (Bézout ignores physical limits); reduce with an empty edge case; folding gcd short-circuits at 1 — mention the early exit.

LC 1071 Greatest Common Divisor of StringsLC 914 X of a Kind in a Deck of CardsLC 365 Water and Jug Problem
Example 1: Greatest Common Divisor of Strings (LC 1071)str1 = "ABCABC", str2 = "ABC".
  • First check a common block even exists: str1 + str2 == str2 + str1? "ABCABCABC" == "ABCABCABC" ✓ → they're both repetitions of one block.
  • The block's length is gcd(6, 3) = 3, so the largest common divisor string is the first 3 chars → "ABC". ✓ The concatenation-commutes test replaces a pile of case analysis.

4Primes: Sieve, Factorization, and Prime Counting

What it is: Anything needing many primality answers or prime factorizations: count primes below n, factor every element of an array, permutations constrained by primality. One precomputation — the sieve — converts per-query cost from O(√n) to O(1)-ish.

Intuition: primality of one number → trial division by candidates ≤ √n (any composite has a factor ≤ its square root). Primality of many numbers up to n → flip the direction: each prime announces its multiples — the sieve, O(n log log n). The upgrade: record for every number its smallest prime factor (SPF) during the sieve; then factoring any x is following SPF links — O(log x).

Approach: sieve template: is_prime = [True]*n, kill 0/1, for i in 2..isqrt(n): if prime, mark i*i, i*i+i, … False (starting at i*i because smaller multiples were killed by smaller primes). SPF variant: store spf[j] = i on first marking.

Challenges & pitfalls

starting marks at 2*i instead of i*i (correct but misses the optimization and its explanation); range(i*i, n, i) bounds off-by-one; factoring by trial division when SPF was the intent; for one-shot primality of a huge number, trial division to √n is the interview answer (Miller–Rabin is a name-drop).

LC 204 Count PrimesLC 2521 Distinct Prime Factors of Product of ArrayLC 1175 Prime Arrangements
Example 1: Count Primes (LC 204) — count primes below n = 10.
  • Sieve: start all of 2..9 marked prime. Take 2 (prime) → cross out 4, 6, 8. Take 3 (prime) → cross out 9 (6 already gone). 4 > √10 so stop marking.
  • Survivors: 2, 3, 5, 7 → 4 primes. ✓ Each prime announced its own multiples; starting the crossing-out at (here 4 for i=2, 9 for i=3) avoids redoing work smaller primes already did.

5Divisor Enumeration (the √n mirror)

What it is: List, count, or sum the divisors of n — kth factor, perfect numbers, numbers with exactly four divisors. The single trick: divisors come in pairs (i, n/i) straddling √n, so full enumeration costs O(√n).

Intuition: if i | n then n/i | n, and one of the pair is ≤ √n — so scanning i = 1..⌊√n⌋ finds every divisor exactly once as the small half of its pair. Perfect square ⇒ i == n/i once — the self-paired middle. Formula view: if n = ∏ pᵢ^aᵢ, then #divisors = ∏(aᵢ+1) — knowing it lets you sanity-check (1390's "exactly four" means p·q or ).

Approach: kth factor (1492): first pass over i ≤ √n collects small divisors counting toward k; second pass walks i back down, emitting large partners n//i in increasing order — skipping the middle when i*i == n. Perfect number (507): sum both halves of each pair, subtract n, compare.

Challenges & pitfalls

the perfect-square double-count (every problem here hides it); emitting large divisors in order for 1492; 1 and n inclusion (507 excludes n); loop bound i*i <= n vs i <= isqrt(n) (both fine; float sqrt is not); the complexity claim ("O(√n) per query — for many queries I'd precompute").

LC 1492 The kth Factor of nLC 507 Perfect NumberLC 1390 Four Divisors
Example 1: The kth Factor of n (LC 1492)n = 12, k = 3.
  • Divisors of 12, in order: 1, 2, 3, 4, 6, 12. Enumerate small halves up to √12 ≈ 3: 1 (partner 12), 2 (partner 6), 3 (partner 4).
  • Counting in increasing order, the 3rd factor is 3. ✓ You'd find the small divisors going up (1, 2, 3) and the large ones by walking their partners back down (4, 6, 12) — all in O(√n).

6Modular Arithmetic & Fast Exponentiation (binary doubling)

What it is: Compute x^n (or anything defined by repeated combination) for astronomically large n by squaring: n halves every step, O(log n). Under a modulus, this plus modular inverses is the engine behind every "count … mod 10⁹+7" problem.

Intuition: x^n = (x²)^(n/2), times one extra x when n is odd — each squaring consumes one binary digit of the exponent. Read n in binary: x^13 = x^8 · x^4 · x^1. The same doubling computes division without / (29), matrix powers (Fibonacci in O(log n)), and repeated composition. Super pow (372): process the exponent's digits, or reduce with Fermat (a^b ≡ a^(b mod (p−1))).

Approach: iterative template (recite-able):

def power(x, n, m):
    res = 1
    x %= m
    while n:
        if n & 1: res = res * x % m
        x = x * x % m
        n >>= 1
    return res

Python's built-in pow(x, n, m) does exactly this — use it, but be ready to write it. Division under mod = multiply by pow(a, p−2, p) (Fermat, p prime).

Challenges & pitfalls

the recursive version recomputing power(x, n//2) twice (O(n) — bind it or go iterative); forgetting % m on the squaring line; LC 29's INT_MIN / -1 overflow edge; explaining O(log n) ("the exponent loses a bit per iteration"); "anything associative can be doubled."

LC 50 Pow(x, nLC 1922 Count Good NumbersLC 372 Super Pow
Example 1: Pow(x, n) (LC 50) — compute 2^10.
  • Read 10 in binary: 1010 = 8 + 2, so 2^10 = 2^8 · 2^2. Build powers by repeated squaring: 2^1 = 2, 2^2 = 4, 2^4 = 16, 2^8 = 256.
  • Multiply the ones matching set bits: 256 · 4 = 1024. ✓ Only ~log₂(10) ≈ 4 squarings, not 10 multiplications — the difference between O(log n) and O(n) that matters when n is 10¹⁸.

7Combinatorics: Count, Don't Enumerate

What it is: "How many ways/paths/arrangements…" where the answer is a closed form: binomial coefficients, factorials, Catalan numbers, or a small product formula — often mod 10⁹+7. The skill is mapping the story onto a standard counting object.

Intuition: unique paths (62): every path is a shuffle of (m−1) downs and (n−1) rights → C(m+n−2, m−1). Pascal (118/119): C(n,k) = C(n−1,k−1) + C(n−1,k), and row generation in O(k) via the ratio C(n,k+1) = C(n,k)·(n−k)/(k+1). Pickup/delivery (1359): the i-th pair has (2i−1)·i valid slots → ∏ i·(2i−1), discovered by trying n=1,2 by hand. Recognize on sight: C(n,k), Catalan C(2n,n)/(n+1), stars-and-bars, inclusion–exclusion.

Approach: small/one-shot → math.comb. Under a modulus → precompute factorials fact[i] and inverse factorials inv_fact[i] = pow(fact[i], p−2, p) once, then C(n,k) = fact[n]·inv_fact[k]·inv_fact[n−k] % p in O(1). Always state the bijection.

Challenges & pitfalls

dividing under mod without inverses (the #1 combinatorics bug); float math.factorial ratios drifting (use math.comb); off-by-one in the bijection (m+n−2 not m+n); recognizing Catalan dressed up; the confidence to answer "how many" without enumerating.

LC 62 Unique PathsLC 119 Pascal's Triangle IILC 1359 Count All Valid Pickup and Delivery Options
Example 1: Unique Paths (LC 62) — an m = 3 by n = 7 grid, moving only right/down.
  • Any path is a sequence of (m−1) = 2 downs and (n−1) = 6 rights, in some order — so counting paths = counting which of the 2 + 6 = 8 steps are the downs.
  • That's C(8, 2) = 28. Answer 28. ✓ The bijection ("each path ↔ a choice of which steps go down") turns a grid DP into one binomial coefficient.

8Base Conversion & Positional Systems

What it is: Translate numbers between representations: decimal ↔ base-7, hex, Excel columns (base-26 without a zero), even base −2. The universal loop is divmod peeling; the interview content is in the irregular bases.

Intuition: standard base-b conversion is Pattern 1's digit peel with divmod(n, b). Excel columns (168/171) are the famous twist: digits run 1–26 with no zero — a bijective base-26. The fix is one line: subtract 1 before each divmod (n -= 1; n, r = divmod(n, 26)). Negative base (1017): same peel, but a negative remainder must be normalized up.

Approach: to-string: peel with divmod, append, reverse. From-string (171): Horner's rule left to right — n = n * 26 + val(c). For 168 recite "subtract one, then divide" and trace Z (26) and AA (27) by hand before submitting.

Challenges & pitfalls

treating Excel as ordinary base-26 (works until Z, then off-by-one forever); Python divmod with negative operands (verify on n=3 by hand); building strings by prepending (O(n²) — collect and reverse); n = 0 edge in any to-string conversion.

LC 168 Excel Sheet Column TitleLC 171 Excel Sheet Column NumberLC 1017 Convert to Base −2
Example 1: Excel Sheet Column Title (LC 168) — convert n = 28 to its column title.
  • It's base-26 with digits 1–26 and no zero, so subtract 1 before each division:
    • n = 28: 28 − 1 = 27, divmod(27, 26) = (1, 1) → digit 1 → 'B'; carry n = 1.
    • n = 1: 1 − 1 = 0, divmod(0, 26) = (0, 0) → digit 0 → 'A'; n = 0, stop.
  • Reverse the collected letters → "AB". ✓ Check: AB = 26·1 + 2 = 28. The "subtract 1 each round" is what maps 1..26 onto 0..25 so ordinary division works — skip it and Z → AA breaks.

9Sum Formulas & Algebraic Manipulation

What it is: The answer is an algebraic identity away: Gauss sums, telescoping, rearranging an equation until the loop disappears. Missing number via expected-sum, counting odds in a range via prefix subtraction, expressing n as sums of consecutive integers.

Intuition: Gauss: 1+2+…+n = n(n+1)/2 — missing number (268) is expected − actual, one pass. Range counting (1523): define f(x) = count of odds in [0,x] = (x+1)//2, answer f(hi) − f(lo−1) — prefix-function subtraction works for any monotone count. Consecutive-sum (829): n = k·a + k(k−1)/2n − k(k−1)/2 must be positive and divisible by k; loop k while k(k−1)/2 < n → O(√n).

Approach: write the constraint as an equation; isolate the unknown; read off the iteration space and divisibility conditions. Keep everything in integers.

Challenges & pitfalls

hashing/sorting what algebra solves in O(1) (offer the formula first); lo−1 underflow in prefix subtraction; deriving 829's bound live; sign/parity slips when rearranging (verify the formula on two hand cases).

LC 268 Missing NumberLC 1523 Count Odd Numbers in an Interval RangeLC 829 Consecutive Numbers Sum
Example 1: Missing Number (LC 268)nums = [3, 0, 1] contains all of 0..3 except one.
  • The full sum of 0..3 is 3·4/2 = 6 (Gauss). The actual sum is 3 + 0 + 1 = 4.
  • The missing number is 6 − 4 = 2. ✓ One pass, no sorting or set — the formula collapses the search. (XOR of indices and values is an equally valid O(1)-space alternative worth offering.)

10Digit Processes, Fixed Points & Cycles

What it is: Repeatedly apply a digit-based map (sum of squared digits, sum of digits) until something stabilizes. Because the map crushes big numbers into a small range, the orbit must enter a cycle — detect it, or shortcut it with a known invariant.

Intuition: any n above a few hundred maps to something much smaller (sum of squared digits of a 13-digit number ≤ 13·81 = 1053), so all orbits fall into a bounded box and, by pigeonhole, eventually cycle. Happy number (202): a cycle means unhappy → detect with a seen-set or Floyd's tortoise-and-hare on the function. Digital root (258): the shortcut invariant — a number ≡ its digit sum mod 9 ⇒ answer is 1 + (n−1) % 9 for n > 0, O(1), no loop.

Approach: general template: iterate n = f(n) with a seen set until a fixed point or repeat. Upgrade 1: Floyd (O(1) space). Upgrade 2: a mathematical invariant that skips iteration (mod 9 for digit sums). Justify termination before the while-loop.

Challenges & pitfalls

proving the loop terminates (the pigeonhole sentence); the n=0/n=9 edges in the digital-root formula; explaining why mod 9 (10^k ≡ 1); choosing set vs Floyd (offer Floyd as the space upgrade, don't default to the fancy one).

LC 202 Happy NumberLC 258 Add DigitsLC 1837 Sum of Digits in Base K
Example 1: Happy Number (LC 202) — is 19 happy (repeatedly sum the squares of digits, reach 1)?
  • 19 → 1² + 9² = 82 → 8² + 2² = 68 → 6² + 8² = 100 → 1² + 0² + 0² = 1. Reached 1 → happy (true). ✓
  • If it had entered a repeating cycle instead (which a seen-set or Floyd's cycle detection would catch), it'd be unhappy. The map always terminates because big numbers shrink into a bounded range, so by pigeonhole the orbit either hits 1 or loops.
Example 2: Add Digits (LC 258) — the digital root of 38. Looping: 38 → 11 → 2. Or the O(1) invariant: 1 + (38 − 1) % 9 = 1 + 1 = 2. ✓

11Inclusion–Exclusion + LCM Counting (with binary search on the answer)

What it is: "Find the n-th number divisible by a / b / c" or "n-th magical number" — the k-th element of a merged multiples sequence, where n is too big to enumerate. Combine a counting function built from inclusion–exclusion with binary search on the answer.

Intuition: you can't list the sequence, but you can count it: numbers ≤ x divisible by a or b = x//a + x//b − x//lcm(a,b) (subtract the double-counted; for three sets, add back the triple term, and lcm not product). count(x) is monotone in x ⇒ the n-th element is the smallest x with count(x) ≥ n — a boundary search. This composition — NT gives the predicate, binary search finds the boundary — is the pattern.

Approach: write count(x) from inclusion–exclusion (2 or 3 terms); binary search lo = 1, hi = n · min(divisors); return lo % (10**9+7) if asked. Sanity-check count on tiny x by hand against a brute list.

Challenges & pitfalls

using a*b where lcm is required (fails when inputs share factors); sign errors in the 3-set expansion; a too-small hi (silently wrong); the final mod applies to the found value; recognizing "n-th ⟨adjective⟩ number" with huge n.

LC 878 Nth Magical NumberLC 1201 Ugly Number IIILC 2427 Number of Common Factors
Example 1: Nth Magical Number (LC 878)n = 1, a = 2, b = 3 (a magical number is divisible by a or b); find the 1st.
  • Count of magical numbers ≤ x: count(x) = x//2 + x//3 − x//lcm(2,3) = x//2 + x//3 − x//6.
  • Binary-search the smallest x with count(x) ≥ 1: at x = 2, count = 1 + 0 − 0 = 1 ≥ 1, and at x = 1, count = 0. So the boundary is 2.
  • Answer 2. ✓ Using lcm(2,3) = 6 (not 2·3) for the overlap term is the detail adversarial tests probe.

12Game Theory: Parity, Invariants & Backward Induction

What it is: Two players alternate moves, both playing optimally — who wins? The LC versions almost always collapse to a parity/invariant one-liner, and the interview is about finding it (via small cases) and proving it (via strategy or induction).

Intuition: work backward from losing positions. Nim (292): positions 1–3 win (take all), 4 loses (every move hands opponent 1–3), pattern locks in → n % 4 != 0; the proof is a strategy (whatever k the opponent takes, you take 4−k). Divisor game (1025): losing exactly when n is odd; parity is the invariant → n % 2 == 0. Stone game (877): with an even number of piles and unequal total, first player can commit to all-even or all-odd indexed piles → always true.

Approach: the method is the deliverable: (1) hand-compute win/lose for n = 1..8; (2) conjecture the pattern; (3) prove by exhibiting a strategy that preserves an invariant. If no clean pattern → it's a DP/minimax game, not a formula game.

Challenges & pitfalls

answering the formula without the strategy (interviewer asks "why?"); confusing "optimal" with "greedy" in small cases; 877's trap (coding interval DP when a two-line argument suffices); saying the method out loud so silence doesn't read as stuck.

LC 292 Nim GameLC 1025 Divisor GameLC 877 Stone Game
Example 1: Nim Game (LC 292) — you may take 1–3 stones per turn; last to take a stone wins. Do you win with n = 4?
  • Tabulate: n=1,2,3 are wins (take them all). n=4: whatever you take (1, 2, or 3) leaves 3, 2, or 1 — all wins for your opponent → 4 is a loss.
  • The pattern: you lose exactly when n is a multiple of 4 → answer for n=4 is false. ✓ The proof is a strategy: keep the count a multiple of 4 for your opponent by taking 4 − (their move) each turn. (n=7 → 7 % 4 ≠ 0 → true.)

13Geometry Essentials (integer-safe)

What it is: The small set of geometry problems that actually appear: points on a line, rectangle overlap/union area, distances. The unifying rule: stay in integers — cross-multiplied slopes, squared distances, interval intersections — and float bugs become unrepresentable.

Intuition: max points on a line (149): anchor each point; every other point defines a direction — same line ⟺ same reduced slope. Represent slope as a canonical fraction (dy//g, dx//g) with g = gcd and a fixed sign — hashable, exact, no division. Rectangles (223/836): work per-axis — two boxes overlap iff they overlap on x and on y; 1-D overlap length is max(0, min(r1, r2) − max(l1, l2)); union area = A + B − overlap.

Approach: 149: double loop with a per-anchor hashmap of direction → count; normalize (dy, dx) by gcd and force a canonical sign. Rectangles: dx = max(0, …), dy = max(0, …); overlap strictness (836 wants positive area — > not ). Distances: compare squared distances.

Challenges & pitfalls

vertical lines nuking float slope code (dx = 0 — integer pairs sidestep it); sign normalization so (1,−2) and (−1,2) hash together; 32-bit overflow in dx·dy; strict-vs-touching overlap (read the definition); convex hull / line-sweep are rare — deprioritize.

LC 149 Max Points on a LineLC 223 Rectangle AreaLC 836 Rectangle Overlap
Example 1: Rectangle Overlap (LC 836) — do rec1 = [0,0,2,2] and rec2 = [1,1,3,3] overlap with positive area?
  • Check each axis separately. X: overlap length = max(0, min(2,3) − max(0,1)) = max(0, 2 − 1) = 1 > 0. Y: max(0, min(2,3) − max(0,1)) = 1 > 0.
  • Both axes overlap positively → true. ✓ De-dimensioning the 2-D question into two 1-D interval checks, all in integers, avoids any floating-point comparison.

14Probability & Sampling (weighted pick, rejection, reservoir)

What it is: Design-flavored randomness: pick an index proportionally to weights, build a fair rand10 from rand7, sample uniformly from a stream of unknown length. Each has one named technique, and each demands you prove uniformity, not just produce randomness. (Full treatment in probability.)

Intuition: weighted pick (528): lay the weights end-to-end as segments on a number line — prefix sums; a uniform dart r ∈ [1, total] lands in exactly one segment; find it with binary search — probability ∝ segment length by construction. rand10-from-rand7 (470): rejection sampling — two rand7 calls give a uniform 1..49; accept ≤ 40 and take % 10 + 1, else retry. Reservoir sampling (382): keep the i-th element with probability 1/i; P(item i survives) telescopes to 1/n.

Approach: 528: precompute the prefix array; per query bisect_left(prefix, randint(1, total)). 470: while-loop rejection; never "fix up" rejected values. 382: single pass, random.randint(1, i) == 1 → replace.

Challenges & pitfalls

proving uniformity is the actual interview (rehearse all three 2-sentence proofs); off-by-one between bisect_left/bisect_right; using rejected samples in 470 (bias — explain why); the reservoir trigger phrase ("unknown length / single pass / O(1) memory"); the expected-cost analysis for rejection.

LC 528 Random Pick with WeightLC 470 Implement Rand10(LC 382 Linked List Random Node
Example 1: Random Pick with Weight (LC 528) — weights [1, 3]; index 0 should come up 1/4 of the time, index 1 three-quarters.
  • Prefix sums [1, 4] cut a number line 1..4 into segments: [1] for index 0, [2, 3, 4] for index 1.
  • Throw a uniform dart r ∈ [1, 4] and binary-search the first prefix ≥ r: r = 1 → index 0; r = 2, 3, 4 → index 1.
  • The segment lengths are 1 and 3, so the probabilities are exactly 1/4 and 3/4. ✓ The uniformity proof is the construction — "probability ∝ segment length."

Summary Table — Recognition Cheat Sheet

#PatternTrigger phrase in problemCore toolOne-line key fact
1Digit peel"reverse integer", "palindrome number"divmod(n, 10)build reversed: rev*10 + d; check overflow before push
2Big-number strings"given as strings", "without int conversion"schoolbook + carrydigit i × digit j → positions i+j, i+j+1
3GCD / Bézoutcommon chunk/group size, two jugsEuclid, reduce(gcd)ax+by=c solvable iff gcd(a,b) divides c
4Primes / sieve"count primes", factor many numberssieve (+ SPF)mark from i²; SPF gives O(log x) factorization
5Divisors"kth factor", "perfect number"√n pairingdivisors pair (i, n/i); square = self-pair
6Fast power / modhuge exponent, "mod 1e9+7", no / allowedbinary doublingworks for anything associative; O(log n)
7Combinatorics"how many ways", grid pathsnCr, fact+inv_factdivision under mod = multiply by inverse
8Base conversionExcel columns, base k, base −2divmod peelbijective base-26: subtract 1 each round
9Sum formulas"missing", ranges, consecutive sumsGauss, prefix f(hi)−f(lo−1)algebra first; the loop bound falls out
10Digit cycles"repeat until", happy numberseen-set / Floyd / mod 9bounded orbit ⇒ pigeonhole ⇒ cycle
11Incl–excl counting"n-th number divisible by…"count(x) + BS on answeruse lcm, not product; ± alternation
12Game paritytwo players, optimal playsmall cases → invariantprove with a strategy, not vibes
13Geometrypoints/lines/rectanglesinteger slopes, per-axisslope = reduced (dy, dx) pair; never float ==
14Samplingrandom pick, stream samplingprefix+BS, rejection, reservoirprove uniformity — that's the question
Study order: 1 → 2 (mechanical confidence) → 6 (the single most load-bearing technique — drill until the template is automatic) → 3 → 5 → 4 → 9 → 8 (memorize the Excel −1 trick) → 7 → 10 → 11 (composes two files' skills) → 12 → 14 → 13.
The interview sentence for any of these (per your communication playbook §1.3): "The bounds rule out simulation, so there's structure to exploit — let me work n = 1..5 by hand and find it. ⟨identity⟩ holds because ⟨one-line reason⟩, which gives an O(⟨log n / √n / 1⟩) solution; I'll verify the formula against brute force on a small case before finalizing."