LC Patterns — Combinatorics

This file deepens Pattern 7 of math number theory into a full topic. Modular mechanics (fact/inv_fact, Fermat inverses) live there in §0 — assumed here.
Per-pattern template: What it is → Intuition → Approach/template → Challenges & pitfalls → LC problems (max 3) → Worked examples.

The Master Insight (read before the patterns)

Combinatorics problems ask "how many?" and the losing move is to generate. Every pattern here is a way to count a set without listing it: decompose it into independent choices (multiply), split it into disjoint cases (add), map it onto a set you already know how to count (bijection), or count each element's contribution instead of each object (linearity).

Recognition trigger: "number of ways", "how many distinct", "count the arrangements/subsequences/pairs", "return the k-th ⟨object⟩ without generating", answer mod 10⁹+7 with bounds that make enumeration absurd. Counter-trigger: if choices interact with sequence history in ways no formula captures ("no two adjacent", "sum ≤ k along the way") → it's counting DP, not closed-form combinatorics — knowing which side you're on within 60 seconds is the skill.

The four counting moves, in the order you should try them:

  1. Multiply independent stages — if a choice at stage i never constrains stage j, ways = ∏ (options per stage).
  2. Add disjoint cases — partition the objects by some feature; count each class; sum.
  3. Bijection — "each X corresponds to exactly one Y" where Y is countable (paths ↔ letter shuffles, trees ↔ parenthesizations). State the bijection out loud; it is the proof.
  4. Linearity / contribution flip — instead of Σ over objects of f(object), compute Σ over elements of (number of objects containing it) × (element's contribution). Turns exponential sums into one pass.

And the two repair tools when a direct count overshoots: divide by symmetry (each object counted k times ⇒ divide by k) and inclusion–exclusion (subtract overlaps with alternating signs).

The interview habit that matters most here: verify every formula against brute force on n = 2, 3 before trusting it — a bijection that's off by one is confidently, silently wrong. Say "let me sanity-check against the n=3 case by hand" — it reads as rigor, not doubt.

§0Mechanics & Universal Pitfalls

Computing C(n, k) — pick by situation

import math
math.comb(n, k)                    # exact, no mod — one-shot, moderate n
# Under mod, many queries: precompute once —
MOD = 10**9 + 7
fact = [1] * (N + 1)
for i in range(1, N + 1): fact[i] = fact[i-1] * i % MOD
inv_fact = [1] * (N + 1)
inv_fact[N] = pow(fact[N], MOD - 2, MOD)
for i in range(N, 0, -1): inv_fact[i-1] = inv_fact[i] * i % MOD
def C(n, k):
    if k < 0 or k > n: return 0
    return fact[n] * inv_fact[k] % MOD * inv_fact[n-k] % MOD

Third option — Pascal's row in O(k) via the ratio C(n, k+1) = C(n, k) · (n−k) // (k+1): multiply before dividing and it stays exact in integers (LC 119's intended trick).

Identities worth having on tap

  • Symmetry C(n,k) = C(n,n−k); Pascal C(n,k) = C(n−1,k−1) + C(n−1,k).
  • Interleaving: ways to merge two sequences of lengths m, n preserving internal order = C(m+n, m). Quietly powers half of this file.
  • Subsets: Σₖ C(n,k) = 2ⁿ; permutations P(n,k) = n!/(n−k)!; multinomial n! / (a!·b!·c!).
  • Catalan: Cat(n) = C(2n,n)/(n+1), recurrence Cat(n+1) = Σ Cat(i)·Cat(n−i); first values 1, 1, 2, 5, 14, 42.
  • Stars and bars: non-negative solutions of x₁+…+xₖ = n is C(n+k−1, k−1).

Universal pitfalls

  1. Ordered vs unordered — pairs (i, j): is (j, i) the same object? C(k,2) vs k(k−1). Decide before counting; LC 1512 vs 447 differ exactly here.
  2. Overcounting without noticing — every "multiply the choices" needs the independence sentence; if stages constrain each other, the product is wrong.
  3. Division under mod without a modular inverse — and C(n,k) must return 0 for k < 0 or k > n rather than crash.
  4. Formula ≠ DP confusion — if bounds are small (n ≤ 1000), DP is safer under pressure and equally accepted. Say which you're choosing and why.
  5. Skipping the empty case2ⁿ counts the empty subset; problems often exclude it (−1 at the end).

1Multiplication & Addition Principles (independent stages)

What it is: The answer decomposes into a sequence of independent decisions — count options per stage and multiply; where the structure branches into disjoint shapes, count each and add. The rest of combinatorics is this pattern with better costumes.

Intuition: good numbers (1922): each even index independently takes 5 values, each odd index 4 → 5^⌈n/2⌉ · 4^⌊n/2⌋ — huge n, so fast power finishes it. Unique digits (357): build numbers digit by digit — first digit 9 options (no 0), second 9 (0 allowed, one used), then 8, 7, … — a falling product summed over lengths. Pickup/delivery (1359): the i-th pair drops into 2i−1 gaps × i orderings → ∏ i(2i−1), discovered by hand-computing n = 1, 2.

Approach: narrate stages, verify independence ("the choice at position i doesn't restrict position j because…"), write the product, compute with a loop + mod (or fast power when stages repeat). When the count varies by a feature (length, first digit), sum over that feature's disjoint classes. Small-case verification is non-negotiable.

Challenges & pitfalls

false independence (counting strings "without repeated letters" as 26ⁿ); forgetting to sum disjoint cases; recognizing the repeated-stage → fast-power upgrade when n reaches 10¹⁵; presenting the product without the independence sentence.

LC 1922 Count Good NumbersLC 357 Count Numbers with Unique DigitsLC 1359 Count All Valid Pickup and Delivery Options
Example 1: Count Numbers with Unique Digits (LC 357) — count numbers in [0, 10ⁿ) with all-distinct digits, for n = 2.
  • Sum over disjoint lengths (addition principle), multiplying within each length:
    • length 0 → just the number 0: 1.
    • length 1 (1..9): 9 choices.
    • length 2: first digit 9 options (no leading 0), second digit 9 options (0 now allowed, but one digit already used) → 9 × 9 = 81.
  • Total 1 + 9 + 81 = 91. ✓ Within a length the digit choices are independent (each just excludes the used ones); across lengths the cases are disjoint, so you add.

2Binomial Coefficients & Lattice Paths (choosing positions)

What it is: The object is determined by which positions get which of two labels — grid paths (which steps go right), step sequences (which steps go +1) — so the count is a single C(n, k).

Intuition: unique paths (62): any monotone path in an m×n grid is a string of (m−1) D's and (n−1) R's; the path is the choice of R-positions → C(m+n−2, m−1). Reach position after k steps (2400): to land displacement d in k unit steps, you need (k+d)/2 rights → C(k, (k+d)/2), and 0 when k+d is odd or |d| > k. Pascal's row (119): generate row n in O(k) by the running-ratio identity.

Approach: find the two-label description ("each object ↔ a choice of which k of n slots are X"); write C(n, k); guard impossible parities/ranges with 0. For the DP-vs-formula fork on 62: both accepted; formula shows insight, DP generalizes to obstacles.

Challenges & pitfalls

off-by-one in the bijection (m+n−2, not m+n); parity guards forgotten in 2400 (returns garbage instead of 0); ratio-method integer division order; when obstacles appear, the formula dies and DP takes over.

LC 62 Unique PathsLC 119 Pascal's Triangle IILC 2400 Number of Ways to Reach a Position After Exactly k Steps
Example 1: Ways to Reach a Position After k Steps (LC 2400) — start at 1, end at 2, exactly k = 3 unit steps (±1 each).
  • Net displacement d = 2 − 1 = 1. In 3 steps, if r are rights and l lefts, r + l = 3 and r − l = 1r = 2.
  • The object is "which 2 of the 3 steps are rights" → C(3, 2) = 3. ✓ The guards matter: if k + d were odd (unreachable parity) or |d| > k, the answer would be 0 — here k + d = 4 is even and reachable.

3Interleavings & Multinomials (merge counts, preserve order)

What it is: Count ways to merge sequences whose internal order is fixed — shuffle two subtree orders, schedule tasks respecting per-chain order. The atom: merging lengths m and n = C(m+n, m); merging many groups = the multinomial (Σsizes)! / ∏(sizeᵢ!).

Intuition: the merged sequence is determined by which slots each group occupies (its internal order fills them uniquely). Same-BST reorderings (1569): the root must come first; left- and right-subtree elements interleave freely → ways(root) = C(L+R, L) · ways(left) · ways(right). Build rooms (1916): topological orderings of a tree = n! / ∏(subtree_size(v)).

Approach: identify the fixed-order chains/subtrees; count interleavings top-down: at each combine point multiply children's counts by the binomial distributing slots. Precompute fact/inv_fact to make every C O(1). Verify on a 3-node tree by hand.

Challenges & pitfalls

believing internal order is actually fixed (in 1569, the recursion handles within-subtree order — don't double-count); the −1 for excluding the identity arrangement (1569); subtree sizes vs node counts off-by-one in 1916; the meta-recognition — "relative order within groups fixed, groups shuffle" ⇒ C(m+n, m).

LC 1569 Number of Ways to Reorder Array to Get Same BSTLC 1916 Count Ways to Build Rooms in an Ant Colony
Example 1: Reorder Array to Get Same BST (LC 1569) — how many reorderings of [2, 1, 3] build the same BST (excluding the original)?
  • Inserting [2, 1, 3] makes root 2, left subtree {1}, right subtree {3}. To rebuild the same tree, 2 must come first, but the left element 1 and right element 3 can interleave in any order among the remaining 2 slots.
  • Ways = C(L+R, L) · ways(left) · ways(right) = C(1+1, 1) · 1 · 1 = 2 total orderings ([2,1,3] and [2,3,1]). Excluding the original → 2 − 1 = 1. ✓ The binomial C(2,1) counts how the two independent subtree streams interleave.

4Catalan Numbers (balanced / non-crossing structures)

What it is: One number sequence — 1, 1, 2, 5, 14, 42, 132… — counts a shocking family of objects: balanced parentheses, distinct BSTs, full binary trees, monotone paths staying below the diagonal, non-crossing chords. Recognize the shape, name Catalan, and the problem is done.

Intuition: the recurrence is a first-decision split: fix the first structural choice (the root; the match of the first '('), and the object splits into two smaller independent instances → Cat(n+1) = Σᵢ Cat(i)·Cat(n−i). Unique BSTs (96): choose root k → left subtree from k−1 keys, right from n−k → exactly the recurrence. Generate parentheses (22): the count is Cat(n) — a strong moment to answer "42 for n=5" mid-backtracking.

Approach: small n (all these problems): DP the convolution in O(n²) — clean and mod-safe. Closed form C(2n,n)/(n+1) (or C(2n,n) − C(2n,n+1) — subtraction form avoids inverses) when n is large.

Challenges & pitfalls

recognizing Catalan in costume (trigger words: balanced, non-crossing, valid nesting, distinct shapesmemorize 1, 2, 5, 14); the recurrence's index gymnastics (left size i, right size n−1−i); 894 parity (even n → 0 trees); dividing by n+1 under mod without an inverse.

LC 96 Unique Binary Search TreesLC 894 All Possible Full Binary Trees — count first, then buildLC 22 Generate Parentheses — know its count
Example 1: Unique Binary Search Trees (LC 96) — how many distinct BSTs hold 1..n, for n = 3?
  • Condition on the root: root k uses k−1 keys on the left, n−k on the right, and the two sides are independent → multiply, sum over k.
  • Cat(0)=1, Cat(1)=1, Cat(2)=2. Cat(3) = Cat(0)·Cat(2) + Cat(1)·Cat(1) + Cat(2)·Cat(0) = 2 + 1 + 2 = 5.
  • Answer 5 — the 3rd Catalan number. ✓ Seeing the sequence 1, 1, 2, 5 emerge from your small cases is the signal to name Catalan.

5Group, Then Choose (hashmap + C(k, 2))

What it is: Count pairs (or triples) of "equivalent" items — equal values, same ratio, same distance. Group items by an equivalence key with a hashmap; each group of size k contributes C(k,2) unordered or k(k−1) ordered pairs; sum over groups.

Intuition: a pair is "good" iff both members share some computable signature — so pair-counting collapses to key design plus one identity. Good pairs (1512): key = value, Σ C(k,2). Interchangeable rectangles (2001): key = reduced ratio (w//g, h//g) — never a float. Boomerangs (447): per anchor, key = squared distance; ordered pairs → Σ k(k−1). Streaming refinement: for each new item, answer += count[key] then increment — pairs counted once with i < j for free.

Approach: design the canonical key (reduce fractions by gcd; sort tuple components when order shouldn't matter; squared distances to stay integer); one pass to group (Counter); one pass over group sizes applying C(k,2) / k(k−1).

Challenges & pitfalls

ordered vs unordered (447 is ordered! — read the object's definition); non-canonical keys splitting a group; add-then-increment order in streaming form; per-anchor maps leaking across anchors in 447; saying the identity's story ("k items, each unordered pair once: k choose 2").

LC 1512 Number of Good PairsLC 447 Number of BoomerangsLC 2001 Number of Pairs of Interchangeable Rectangles
Example 1: Number of Good Pairs (LC 1512)nums = [1, 2, 3, 1, 1, 3]; count pairs (i, j) with i < j and nums[i] == nums[j].
  • Group by value: 1 appears 3 times, 3 appears 2 times, 2 once.
  • Each group of size k gives C(k, 2) unordered pairs: value 1 → C(3,2) = 3; value 3 → C(2,2) = 1; value 2 → 0.
  • Total 3 + 1 = 4. ✓ Grouping turns an O(n²) pair scan into "count each equivalence class, apply one identity." Because i < j is unordered, it's C(k,2), not k(k−1).

6Contribution Counting (flip the sum)

What it is: Asked for a sum over an exponential family — all subsequences, all subarrays — flip it: for each element (or pair), count how many family members it appears in (with what role), multiply, and sum. Linearity turns 2ⁿ objects into n terms.

Intuition: subsequence widths (891): Σ(max−min) over 2ⁿ subsequences — but sort (widths don't care about order) and element a[i] is the max of exactly 2^i subsequences and the min of 2^(n−1−i) → Σ a[i]·(2^i − 2^(n−1−i)). Subarray minimums (907): element a[i] is the minimum of left · right subarrays, where left/right = distances to the previous-smaller and next-smaller elements (a monotonic stack); contribution a[i]·left·right.

Approach: three steps: (1) reorder/normalize if the objective permits (sorting kills order-dependence — state why it's legal); (2) for each element, derive "in how many objects does it play role R?" — usually a power of 2 or a product of spans; (3) one pass with precomputed powers of 2 mod p. The tie-break in 907: strict-less on one side, ≤ on the other, so equal minimums count once.

Challenges & pitfalls

the flip itself ("sum over objects → sum over elements × multiplicity"); justifying the sort (legal when the statistic is order-free); duplicates double-counted in span products (the strict/non-strict convention); powers of 2 recomputed with pow per element instead of a prefix table.

LC 891 Sum of Subsequence WidthsLC 1498 Number of Subsequences That Satisfy the Given Sum ConditionLC 907 Sum of Subarray Minimums
Example 1: Sum of Subarray Minimums (LC 907)arr = [3, 1, 2, 4]; sum the minimum of every contiguous subarray.
  • Flip it: instead of listing subarrays, ask each element "for how many subarrays am I the minimum?" That's left · right, where left = how far you can extend leftward before a smaller element, right = rightward.
    • 3 (idx 0): smaller element immediately at idx 1 → left=1, right=1 → contributes 3·1·1 = 3.
    • 1 (idx 1): nothing smaller either side → left=2, right=31·2·3 = 6.
    • 2 (idx 2): smaller 1 on the left → left=1, right=22·1·2 = 4.
    • 4 (idx 3): smaller 2 on the left → left=1, right=14·1·1 = 4.
  • Total 3 + 6 + 4 + 4 = 17. ✓ Counting each element's contribution (via a monotonic stack for the spans) replaces an O(n²) enumeration of subarrays.

7Inclusion–Exclusion (subtract the overlaps, alternate the signs)

What it is: Count "divisible by any of…" / "having at least one of…" where the easy counts overlap: add singles, subtract pairwise intersections, add back triples — signs alternating by subset parity. On LC the intersections are almost always LCMs.

Intuition: |A ∪ B ∪ C| = Σ|single| − Σ|pair| + |triple| — each element counted once no matter how many sets it's in. Multiples ≤ x of a: x // a; of both a and b: x // lcm(a,b)lcm, never a·b. Nth magical (878): 2 sets + monotone count → binary search on the answer. Kth smallest coin amount (3116): up to 15 coins → iterate all 2¹⁵ subsets, sign = subset-size parity, term = x // lcm(subset).

Approach: template for the general case: for mask in 1..2^m − 1: compute l = lcm of chosen, early-break if l > x; count += (+1 if popcount odd else −1) * (x // l). Wrap in a boundary-search when the ask is "k-th" rather than "how many ≤ x". Sanity-check count(x) against a brute list for x ≤ 50.

Challenges & pitfalls

product-instead-of-lcm (it's that common); sign errors past 3 sets (popcount parity); lcm overflow without the early break; duplicated divisors in input (dedupe first); keeping the counting layer and the k-th-element (binary search) layer cleanly separated.

LC 2652 Sum MultiplesLC 878 Nth Magical NumberLC 3116 Kth Smallest Amount With Single Denomination Combination
Example 1: Sum Multiples (LC 2652) — sum of all numbers in [1, n] divisible by 3, 5, or 7, for n = 7.
  • The numbers ≤ 7 divisible by any of them: 3, 5, 6 (div by 3), 5 (div by 5), 7 (div by 7). Distinct set {3, 5, 6, 7}, sum = 21.
  • Inclusion–exclusion view: (multiples of 3: 3+6=9) + (of 5: 5) + (of 7: 7) − (of 15, 21, 35 — all > 7, so 0) + (of 105 — 0) = 9 + 5 + 7 = 21. ✓ The overlap terms use lcm (15, 21, 35), which here exceed n and vanish — but using 3·5 = 15 vs lcm(3,5) = 15 happens to match only because 3 and 5 are coprime; for 4 and 6 you'd need lcm = 12, not 24.

8Combinatorial Unranking (build the k-th object, no enumeration)

What it is: "Return the k-th permutation/instruction-string/happy-string" with k up to billions: construct the answer position by position — at each slot, count how many objects start with each candidate prefix, and walk past whole blocks until k lands inside one.

Intuition: objects in sorted order cluster into blocks by first choice, and block sizes are computable: permutations starting with a fixed first element — (n−1)!; instruction strings starting with 'H' — C(remaining−1, remaining V's); happy strings with a fixed first char — 2^(n−1). So the k-th object's first symbol is found by subtracting block sizes from k until it fits, then recurse on the suffix. This is positional notation generalized (60 is writing k in factorial base).

Approach: convert to 0-indexed k first (k -= 1 — do it once, immediately). Per position: for each candidate symbol in sorted order, compute block = count of completions; if k >= block: k -= block else commit the symbol and descend. For 60, maintain the shrinking list of unused digits.

Challenges & pitfalls

the 1-vs-0 index conversion (the bug of this pattern); block-count formulas under constraints; mutable candidate sets in 60 (index into remaining digits); explaining the skip-blocks idea cleanly.

LC 60 Permutation SequenceLC 1643 Kth Smallest InstructionsLC 1415 The k-th Lexicographical String of All Happy Strings of Length n
Example 1: Permutation Sequence (LC 60) — the k = 3rd permutation of 1, 2, 3 in sorted order.
  • Convert to 0-indexed: k = 2. Digits available: [1, 2, 3].
  • Position 1: each first digit heads a block of (3−1)! = 2 permutations. Block index = 2 // 2 = 1 → pick digits[1] = 2; new k = 2 % 2 = 0; remaining [1, 3].
  • Position 2: block size (2−1)! = 1. Index = 0 // 1 = 0 → pick digits[0] = 1; k = 0; remaining [3].
  • Position 3: pick 3.
  • Result "213". ✓ Check: sorted permutations are 123, 132, 213, 231, 312, 321 — the 3rd is 213. Skipping whole (n−1)! blocks avoids ever generating the earlier permutations.

9Counting in Digit / Prefix Trees (count numbers ≤ N with structure)

What it is: Count or rank numbers below a bound by their decimal structure — how many contain only certain digits, how many 1s appear across all numbers, the k-th number in lexicographic order. Model numbers as paths in a 10-ary trie; count whole subtrees, walk the boundary.

Intuition: numbers ≤ N with digits from a set (902): count by length — for lengths < len(N), free choice |D|^len; for length == len(N), walk N's digits left to right, at each position adding the count of allowed digits strictly below N[i] (each opens a free suffix), staying tight on an equal digit. K-th lexicographic number (440): the trie ordering is preorder; steps(prefix) = size of the prefix's subtree clipped to ≤ N; if k ≥ steps, move to the next sibling, else descend — unranking on the digit trie.

Approach: draw the 10-ary trie once — 902 counts leaves under allowed branches; 233 counts labeled edges; 440 navigates preorder with subtree sizes. Keep the two states of any walk explicit: tight (prefix equals N's prefix) vs free (already smaller).

Challenges & pitfalls

the tight/free distinction evaporating mid-code (name the variables); 440's clip min(next, N+1) off-by-one; 233's current-digit case analysis (derive live from examples); recognizing when constraints exceed formula reach → graduate to digit DP.

LC 902 Numbers At Most N Given Digit SetLC 233 Number of Digit OneLC 440 K-th Smallest in Lexicographical Order
Example 1: K-th Smallest in Lexicographical Order (LC 440) — for n = 13, find the k = 2nd number in lexicographic (dictionary) order.
  • Lexicographic order of 1..13 is: 1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9 (because "10" sorts right after "1").
  • Navigate the digit trie in preorder: start at prefix 1. Its subtree (1, 10, 11, 12, 13) has 5 numbers ≤ 13. Since k = 2 ≤ 5, the answer is inside — step 1 lands on 1 itself, so descend to 10 for step 2.
  • Answer 10. ✓ Counting a prefix's subtree size (clipped to ≤ n) lets you skip or enter whole branches instead of listing numbers — essential when n is up to 10⁹.

Summary Table — Recognition Cheat Sheet

#PatternTrigger phrase in problemCore identity / moveVerify by
1Multiply/add stagesindependent positions/choices∏ options; Σ disjoint casesindependence sentence + n=2
2Binomial / pathsgrid paths, ±1 steps, "choose positions"C(n, k) + parity/range guards2×2 grid by hand
3Interleavingsfixed internal order, free mergeC(m+n, m); n!/∏(subtree sizes)3-node tree
4Catalanbalanced, non-crossing, tree shapesfirst-decision convolution; C(2n,n)/(n+1)spot 1, 2, 5, 14
5Group-then-choosecount equal/similar pairshashmap key + C(k,2) or k(k−1)ordered-vs-unordered check
6Contribution flipΣ over all subsequences/subarrayselement × multiplicity; powers of 2; span productstiny array brute force
7Inclusion–exclusion"divisible by any of", unions± by subset parity; lcm intersectionscount(x) vs brute list
8Unranking"k-th object, k huge"skip blocks by computable size; k -= 1 firstk=1 and k=max cases
9Digit-tree counting"numbers ≤ N with ⟨digit property⟩"tight-prefix walk; subtree sizessmall N by brute force
Study order: 1 → 2 (the bijection habit) → 5 (easy wins, key design) → 6 (the big transferable idea — drill the flip until reflexive) → 4 → 3 → 7 → 8 → 9 (hardest mechanics; also your bridge to digit DP).
The interview sentence for any of these (per your communication playbook §1.3): "Rather than generate, I'll count: each ⟨object⟩ corresponds to ⟨a choice of k positions / an interleaving / a signature⟩, so the count is ⟨identity⟩ — let me verify that against the n = 3 case by hand before coding."