Generating combinations in C
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Generating combinations means choosing k items from n items where order does not matter. In plain C, the usual approach is recursive backtracking or indexed iteration, because the language does not provide a built-in combinations utility.
Core Sections
A recursive backtracking solution
The most common pattern is to build the current combination in a temporary array and recurse forward through the input. Each recursive call decides which next element to include.
This prints:
The key property is that recursive calls only consider positions after the current one, so duplicates and reordered variants are avoided.
How the bounds work
The loop condition i <= n - (k - depth) matters. It prevents useless recursion when there are not enough remaining elements to complete the combination.
At a high level:
- '
startsays where the next pick may begin' - '
depthsays how many elements are already chosen' - '
k - depthsays how many picks are still needed'
That bound is what keeps the recursion correct and efficient.
Generating combinations of indexes instead of values
Sometimes you want the positions, not just the values. That is common when the actual data lives in another structure or when combinations drive further lookups.
Using indexes makes the generator more reusable. You can later map those indexes to strings, structs, or rows in another array.
Bitmask generation for all subset sizes
If you need every subset rather than combinations of a fixed size, a bitmask loop is often simpler than recursion.
This is not the best tool when you only want combinations of exactly k items, but it is handy for exhaustive subset enumeration.
When performance starts to matter
Combination generation grows quickly. Even with efficient code, the count is still combinatorial. For example, choosing 10 items from 30 already creates a large number of results. The practical concern is usually not the recursion overhead but the number of combinations you asked for.
If you are processing each combination, consider whether you can:
- stop early when a target is found
- stream results instead of storing all of them
- prune impossible branches before recursing deeper
Those changes matter much more than micro-optimizing the recursive function.
Common Pitfalls
- Forgetting that combinations ignore order and accidentally generating permutations instead.
- Using the wrong loop bound and recursing into branches that cannot finish.
- Storing every combination in memory when printing or processing them one at a time would be enough.
- Confusing value combinations with index combinations and making the function harder to reuse.
- Expecting a fast solution for very large
nandkeven though the output size itself is enormous.
Summary
- In C, recursive backtracking is the standard way to generate fixed-size combinations.
- The temporary
comboarray holds the current partial result as recursion progresses. - Correct loop bounds prevent invalid branches and reduce wasted work.
- Bitmasking is useful when you want all subsets, not just size-
kcombinations. - The real scalability limit is the number of combinations, not just the implementation details.

