Combinations
Given two integers n and k, return every possible combination of k distinct numbers drawn from the range 1 to n inclusive.
A combination is a set, so order carries no meaning: [1,2] and [2,1] are the same combination and exactly one of them must appear in the output. Each number may be used at most once within a combination.
The combinations themselves may be returned in any order. The output contains C(n, k) entries.
- 1 <= n <= 20
- 1 <= k <= n
- Numbers are drawn from the range [1, n], never 0
- Each number may appear at most once in a given combination
- Output size is C(n, k), which peaks near k = n/2
n = 4, k = 2[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]n = 4, k = 4[[1,2,3,4]]n = 1, k = 1[[1]]n = 5, k = 1[[1],[2],[3],[4],[5]]Pick k numbers from 1..n. Order doesn't matter, so [1,2] and [2,1] are the same set — each must appear once. The trick: only ever pick numbers bigger than the last one you took. Then every set comes out in increasing order and can be built exactly one way, so duplicates are impossible.
Every problem in this section is the same loop — three beats: choose, explore, un-choose.
def backtrack(state):
if done(state):
save(state) # record the finished answer
return
for choice in choices(state): # what can I pick right now?
if not ok(choice):
continue # prune: skip bad picks early
apply(choice) # CHOOSE
backtrack(next_state) # EXPLORE
undo(choice) # UN-CHOOSE: put it backOnly four slots change between problems: done, choices, ok (pruning), and how you finish (save every answer, or return True at the first one). Fill those and the problem is solved.
num from start..n.num + 1).k numbers → save it.k.def combine(n, k):
res, path = [], []
def backtrack(start):
if len(path) == k:
res.append(list(path))
return
for num in range(start, n + 1):
path.append(num) # CHOOSE
backtrack(num + 1) # EXPLORE: only bigger numbers
path.pop() # UN-CHOOSE
backtrack(1)
return resThe one line that matters is backtrack(num + 1): passing num + 1 keeps paths increasing, so no duplicates. Pass num instead and you get Combination Sum; pass start + 1 and you get bugs.
Trace n=4, k=2: from 1 → [1,2],[1,3],[1,4]; from 2 → [2,3],[2,4]; from 3 → [3,4]. Six sets, none repeated — because [2,1] simply can't be built.
Combinations (N=4, K=2)
MINDSET
To avoid duplicates, we only pick numbers strictly larger than our previous pick. This creates a natural ordering and shrinks the search space.
PERFORMANCE
The total number of calls is reduced compared to permutations. We only explore nCk paths where N is the pool size and K is the subset size.