This note covers some of the most common introductory recursion problems asked in coding interviews.
Find
using recursion.
Base case:
def natural_sum(n):
if n == 0:
return 0
return n + natural_sum(n - 1)-
Time Complexity:
$O(n)$ -
Auxiliary Space Complexity:
$O(n)$
Determine whether a string is a palindrome.
- The code calls itself while incrementing the
leftindex and decrementing therightindex. This shrinks the processed string length by exactly 2 characters (1 from each end), represented as$T(n - 2)$ .
Combining these operations gives the recurrence relation:
def is_palindrome(s, left, right):
if left >= right:
return True
if s[left] != s[right]:
return False
return is_palindrome(s, left + 1, right - 1)-
Time Complexity:
$O(n)$ -
Auxiliary Space Complexity:
$O(n)$
Find the sum of all digits of a number.
Example
1234
↓
1 + 2 + 3 + 4 = 10
gives the recurrence relation:
def sum_of_digits(n):
if n == 0:
return 0
return n % 10 + sum_of_digits(n // 10)-
Time Complexity:
$O(d)$ -
Auxiliary Space Complexity:
$O(d)$
where d is the number of digits.
check out DP solution : rope-cutting-with-dp
Given a rope of length n and three possible cut lengths a, b, and c, find the maximum number of pieces obtainable.
If the rope cannot be cut exactly, return -1.
- This generates a ternary recursion tree with a maximum height of (n).
- The total number of operations grows exponentially by a factor of 3 at each depth level.
def max_cuts(n, a, b, c):
if n == 0:
return 0
if n < 0:
return -1
res = max(
max_cuts(n - a, a, b, c),
max_cuts(n - b, a, b, c),
max_cuts(n - c, a, b, c)
)
if res == -1:
return -1
return res + 1-
Time Complexity:
$O(3^n)$ -
Auxiliary Space Complexity:
$O(n)$
See Also:-
Print all subsets of a string or array.
For every element,
-
Include it
-
Exclude it
Each recursive call generates two more recursive calls.
def subsets(s, curr="", i=0):
if i == len(s):
print(curr)
return
subsets(s, curr, i + 1)
subsets(s, curr + s[i], i + 1)-
Time Complexity:
$O(n \times 2^n)$ -
Auxiliary Space Complexity:
$O(n)$
See Also :-
Count the number of subsets whose sum equals a given target.
For every element,
-
Include it
-
Exclude it
def subset_sum(arr, n, target):
if n == 0:
return 1 if target == 0 else 0
return (
subset_sum(arr, n - 1, target)
+
subset_sum(arr, n - 1, target - arr[n - 1])
)-
Time Complexity:
$O(2^n)$ -
Auxiliary Space Complexity:
$O(n)$
See Also :-
Generate every permutation of a string.
Fix one character at the current position and recursively permute the remaining characters.
which expands to
def permutations(s, l=0):
if l == len(s):
print("".join(s))
return
for i in range(l, len(s)):
s[l], s[i] = s[i], s[l]
permutations(s, l + 1)
s[l], s[i] = s[i], s[l]Usage
permutations(list("ABC"))-
Time Complexity:
$O(n \times n!)$ -
Auxiliary Space Complexity:
$O(n)$
(The extra factor of n comes from printing/copying each permutation.)
| Problem | Time Complexity | Auxiliary Space |
|---|---|---|
| Natural Sum | ||
| Palindrome Check | ||
| Sum of Digits | ||
| Rope Cutting | ||
| Generate Subsets | ||
| Subset Sum | ||
| Print Permutations |
| Pattern | Example Problems |
|---|---|
| Single Recursive Call | Natural Sum, Sum of Digits, Palindrome |
| Multiple Recursive Calls | Rope Cutting |
| Include / Exclude | Generate Subsets, Subset Sum |
| Backtracking | Print Permutations |
-
Always identify the base case before writing recursive code.
-
Write the recurrence relation first—it often makes the recursive solution obvious.
-
If each call makes one recursive call, the recursion depth is usually linear.
-
If each call branches into two or more recursive calls, expect exponential time complexity unless Dynamic Programming is used.
-
Problems like Subset Sum, Generate Subsets, and Rope Cutting are often optimized later using DP, so understanding their recursive formulation is the first step.
Quick Rule of Thumb:
One recursive call → Usually linear complexity.
Two recursive calls → Often exponential (
$2^n$).Three recursive calls → Often
$3^n$.Permutations → Usually involve factorial (
$n!$) complexity.