Quant Memo
Core

Generating Permutations and Subsets

Generating every permutation, subset, or combination of a set is a fixed pattern of recursive choices, and knowing the counting formula upfront tells you whether "generate them all" is even feasible.

Prerequisites: Backtracking Search, Big-O Complexity

"Try every possible ordering" or "check every possible subset" comes up constantly — in brute-forcing a small combinatorial optimization, in enumerating candidate portfolios of kk names out of nn, in generating test cases. The generation itself is a small, fixed set of recursive patterns; the part that actually matters is knowing how fast the count explodes, because that tells you the size of nn where "just enumerate them" stops being a plan.

The idea: one recursive choice per position, three variants

Permutations of nn distinct items: at each of nn positions, choose one of the remaining unused items, recurse, then un-choose it (classic backtracking). There are n!n! permutations — 10!3.610! \approx 3.6 million, 15!15! is already 1.3 trillion.

Subsets (the power set) of nn items: at each item, decide include-or-exclude, recurse either way. There are 2n2^n subsets — 2201062^{20} \approx 10^6, 2402^{40} is already 1 trillion. This is exactly the shape used by bitmask DP, where each subset is represented as an integer.

Combinations of size kk out of nn: like subsets, but you stop once kk items are chosen and never reconsider earlier positions once passed, avoiding the same combination being generated in more than one order. The count is (nk)=n!k!(nk)!\binom{n}{k} = \frac{n!}{k!(n-k)!}, which is far smaller than 2n2^n when kk is far from n/2n/2(202)=190\binom{20}{2}=190 versus 2201062^{20}\approx 10^6.

{} a - ab a b - 8 leaves for n=3 → 2^n subsets, one leaf per include/exclude path
Each of the n items forks the tree into include/exclude, so a set of n items always has exactly 2^n leaves — no counting needed, it falls out of the recursion shape.

Worked example: subsets of [1, 2, 3]

Include-or-exclude on 1, then 2, then 3, backtracking-style: exclude 1 → exclude 2 → exclude 3 gives {}; exclude 1 → exclude 2 → include 3 gives {3}; exclude 1 → include 2 → exclude 3 gives {2}; exclude 1 → include 2 → include 3 gives {2,3}; and mirroring all four with 1 included gives {1}, {1,3}, {1,2}, {1,2,3}. Eight subsets total, matching 23=82^3=8.

def subsets(nums):                 # O(2^n) time and output size
    result, partial = [], []
    def backtrack(i):
        if i == len(nums):
            result.append(partial.copy())
            return
        backtrack(i + 1)            # exclude nums[i]
        partial.append(nums[i])
        backtrack(i + 1)            # include nums[i]
        partial.pop()
    backtrack(0)
    return result

Permutations grow as n!n!, subsets as 2n2^n, combinations of size kk as (nk)\binom{n}{k} — memorize these three growth rates, because they tell you instantly whether brute-force enumeration is viable for a given nn before you write a line of code.

If a problem says "choose kk of nn" rather than "all subsets," generate combinations directly (loop from the last chosen index forward) rather than generating all 2n2^n subsets and filtering by size — the difference between (nk)\binom{n}{k} and 2n2^n work is often enormous.

Where it shows up

Interview staples: permutations, subsets, subsets II (with duplicates — sort first, skip repeated siblings), combination sum, letter case permutation. Interviewers watch for whether you know the count before writing the recursion, since it signals you understand the complexity you're about to generate. On a desk, brute-forcing a small basket of 20\le 20 candidate assets for a discrete allocation problem, or enumerating feasible sub-portfolios under a cardinality constraint, both rely on the exact same generation patterns and the same awareness of when nn has grown too large to enumerate.

Related concepts

Practice in interviews

Further reading

  • Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms (ch. C, combinatorics appendix)
ShareTwitterLinkedIn