Trouble designing recursion with limited results
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
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 courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.