What is the best way to generate all binary strings of the given length in Python using Recursion?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The clean recursive solution is to build the string one bit at a time and branch into two recursive calls at each step: one for 0 and one for 1. Since there are 2^n binary strings of length n, recursion maps naturally to the problem as a depth-first traversal of a binary decision tree.
A simple recursive generator
The most useful version is a generator because it yields results one by one instead of building the entire list in memory immediately:
Output:
This works because each call reduces the remaining length by one. The base case is when no positions remain, at which point the current prefix is a complete binary string.
Why this recursive structure is a good fit
At every character position you have exactly two choices, so the recursion tree has two children per node. That makes the algorithm easy to reason about:
- Base case: no positions left, so emit the finished string.
- Recursive case: append
0, then append1.
This direct structure is why recursion is such a natural teaching example here. You do not need extra index bookkeeping or nested loops that change with the target length.
If you want to collect the results into a list instead of streaming them, wrap the generator with list(...):
Return a list directly if needed
If the caller definitely needs all results at once, you can write a list-returning recursive version:
This version is still correct and readable. The generator version is often better for larger inputs because the total number of outputs grows exponentially, and you may not want all of them resident in memory at once.
Complexity and practical limits
No algorithm can avoid the fact that there are 2^n outputs. That means:
- Time complexity is
O(n * 2^n)because you produce2^nstrings and each finished string has lengthn. - Space usage for the generator call stack is
O(n). - Space usage for storing every result is
O(n * 2^n).
This matters quickly. Length 5 gives 32 strings, which is trivial. Length 20 gives 1,048,576 strings, which is already large enough that you should think carefully before building a full list.
Variations on the same idea
You can also write the recursion by tracking the current position explicitly:
This avoids repeated prefix concatenation and is a good pattern when the generated strings are longer or when you want a template for more advanced backtracking problems.
Common Pitfalls
The most common mistake is forgetting the base case or placing it at the wrong depth, which either causes infinite recursion or produces strings of the wrong length.
Another common issue is printing inside the recursive function when the caller actually needs the values returned. Yielding or returning results is more reusable than hard-coding output.
People also underestimate the size of the output. The recursion itself is fine for moderate n, but the total number of strings doubles with each added bit.
Finally, be careful with mutable shared state. If you use a buffer-based approach, always overwrite the current position before each recursive branch so one branch does not leak into the other.
Summary
- The best recursive solution branches on
0and1at each position. - A generator is often preferable because it streams results instead of storing everything at once.
- The base case is when the remaining length reaches zero.
- Output size grows as
2^n, so largenbecomes expensive no matter how elegant the recursion is. - A buffer-based backtracking version is a good optimization when repeated string concatenation becomes a concern.

