Trouble designing recursion with limited results
Data Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.
Introduction
Designing recursion that limits the number of results — such as "find the first N solutions" or "generate combinations up to a maximum count" — requires a different approach than standard recursion. Without a limiting mechanism, a recursive function explores the entire search space. To limit results, you can pass a counter through recursive calls, use a shared mutable collection with an early termination check, yield results with a generator, or use backtracking with pruning. The key challenge is propagating the "stop" signal through the recursion stack efficiently.
The Problem: Unlimited Recursion
For large inputs, this generates millions of results. You only need the first N.
Solution 1: Pass a Counter and Check Early
The check if len(results) < limit prunes branches early, avoiding unnecessary computation.
Solution 2: Generator with yield (Most Pythonic)
Generators naturally support lazy evaluation. Combined with itertools.islice, the recursion only runs as deep as needed to produce the requested results.
Solution 3: Exception-Based Early Termination
Solution 4: Return Boolean for Stop Signal
Solution 5: Backtracking with Pruning (Java/C++)
Common Pitfalls
- Not checking the limit before recursive calls: Checking the limit only at the base case allows unnecessary recursive calls to continue even after enough results are collected. Check the limit before each recursive branch to prune early.
- Mutating shared state without copying:
results.append(current)stores a reference to the same list that gets modified during backtracking. Always append a copy:results.append(current[:])in Python ornew ArrayList<>(current)in Java. - Generator not stopping early: Using
yield fromwithoutisliceor a similar limiter means the generator is ready to produce all results. The caller must stop iteration. If the caller collects into a list withlist(generator), all results are generated. - Returning the wrong signal value: When using a boolean return value to signal "stop", returning
Truefrom all branches (not just the limit-reached branch) causes the recursion to stop prematurely. Only returnTruewhenlen(results) >= limit. - Stack overflow on deep recursion: Limiting results does not limit recursion depth. A search space with millions of nodes may still recurse deeply before finding N results. Set
sys.setrecursionlimit()in Python or convert to an iterative approach with an explicit stack for very deep search spaces.
Summary
- Pass a shared
resultslist and checklen(results) >= limitbefore each recursive branch - Use Python generators with
itertools.islicefor lazy, memory-efficient result limiting - Return a boolean from recursive calls to propagate a "stop" signal up the call stack
- Always copy mutable state (
current[:]) before adding to results during backtracking - For very large search spaces, use iterative approaches with explicit stacks to avoid stack overflow
Related reading
- TSP - Branch and bound
- Tutorial on space complexity of algorithms
- Two elements in array whose xor is maximum
- Two player grid traversal game
- Two salesmen - one always visits the nearest neighbour, the other the farthest
- UIImage - implementing an auto levels algorithm
- Ukkonen's suffix tree algorithm in plain English
- Ukkonen's suffix tree algorithm in plain English

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseData Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.