Recursion and Call Stack
Trace recursive execution, base cases, stack depth, tree-shaped work, and production risks from unbounded call stacks.
What you will be able to do
Recursion is not magic. It is a function calling itself with a smaller version of the problem, while the runtime keeps unfinished calls on the call stack. Understanding that stack is what separates clear recursive reasoning from memorized templates.
Base Case and Recursive Case
Every recursive function needs a base case that stops the chain and a recursive case that makes progress toward that base case. If either part is wrong, the code can loop forever, overflow the stack, or compute the wrong result.
Scenario: Folder Size Calculation
A file manager calculates folder size. A folder can contain files and other folders. This is naturally recursive because each folder asks the same question of its children. But if the folder tree is extremely deep, recursion depth can become a reliability risk.
| Question | Recursive answer | Risk |
|---|---|---|
| What is the base case? | A file returns its own size. | Missing base case causes infinite recursion. |
| What is the recursive case? | A folder sums child sizes. | Repeated traversal can be expensive. |
| What is the depth? | Maximum nested folders. | Deep inputs can overflow the call stack. |
| Can cycles exist? | File systems/symlinks may create revisit risk. | Need visited set or policy. |
Same Pattern in Java, Python, and JavaScript
These examples compute maximum depth of a binary tree. The base case is an empty node. The recursive case asks both children for their depth.
class TreeNode {
int value;
TreeNode left;
TreeNode right;
}
class MaxDepth {
static int depth(TreeNode node) {
if (node == null) return 0;
return 1 + Math.max(depth(node.left), depth(node.right));
}
}Recursion Cost Model
| Cost | Meaning | What to state |
|---|---|---|
| Time | Total work across all calls | Often one call per node/item. |
| Space | Maximum call-stack depth | O(height) for tree recursion, O(n) worst case. |
| Repeated work | Same subproblem solved many times | Dynamic programming fixes this later. |
| Stack overflow | Too many nested calls | Use explicit stack/queue if depth is unsafe. |
Assessment trap
Recursive code can be elegant and still unsafe for deep production inputs. Always state maximum depth and whether the runtime can handle it.
Interview signalFrequently Asked Interview Questions
These are canonical interview patterns for this topic, phrased as concrete problem statements. They avoid vague theory questions and prepare you for the exact reasoning interviewers expect: invariant, edge cases, complexity, and trade-off.
- Compute the maximum depth of a binary tree.
- Invert a binary tree recursively.
- Rewrite recursive DFS with an explicit stack to avoid call-stack overflow.
Production practiceCompany-Style Practice Examples
These are not claimed as exact company-specific questions. They are the interview patterns repeatedly used by product companies to test whether you can move from brute force to a defensible implementation.
| Example | Brute-force approach | Stronger solution | Production notes |
|---|---|---|---|
| Tree max depth | Manually track every path imperatively. | Recursive depth from children plus one. | Call-stack space is tree height. |
| Invert binary tree | Swap one level only. | Swap node children and recurse into subtrees. | Base case handles null. |
| Deep graph DFS | Use recursive DFS blindly. | Use explicit stack when depth is unbounded. | Prevent stack overflow and add visited set. |
Solved modelInterview Question Solutions
Question 1: Maximum Depth of Binary Tree
Compute the maximum depth of a binary tree. Base case is null. Recursive case is one plus the max child depth.
class TreeNode { TreeNode left; TreeNode right; }
class Depth {
static int depth(TreeNode node) {
if (node == null) return 0;
return 1 + Math.max(depth(node.left), depth(node.right));
}
}Question 2: Invert Binary Tree
Invert a binary tree recursively. Swap left and right at the current node, then recurse into both children. The null node is the base case.
class Node { Node left; Node right; }
class Invert { static Node invert(Node node) { if (node == null) return null; Node tmp = node.left; node.left = invert(node.right); node.right = invert(tmp); return node; } }Question 3: Iterative DFS for Deep Inputs
Rewrite recursive DFS with an explicit stack to avoid call-stack overflow. Use your own stack and visited set. This gives control over memory and avoids runtime recursion limits.
import java.util.*;
class Dfs { static List<Integer> dfs(Map<Integer,List<Integer>> g, int start) { Set<Integer> seen = new HashSet<>(); Deque<Integer> stack = new ArrayDeque<>(); List<Integer> out = new ArrayList<>(); stack.push(start); while (!stack.isEmpty()) { int node = stack.pop(); if (!seen.add(node)) continue; out.add(node); for (int next : g.getOrDefault(node, List.of())) stack.push(next); } return out; } }Solved modelWorked Interview Answer
Compute maximum binary-tree depth recursively. The empty node is the base case. Each non-empty node waits for the depths of its children and adds one.
class TreeNode { TreeNode left; TreeNode right; }
class Depth {
static int depth(TreeNode node) {
if (node == null) return 0;
return 1 + Math.max(depth(node.left), depth(node.right));
}
}Hands-on drillTry It Yourself
Practice task
Trace max-depth recursion on a small tree. Write every call frame, the base case returns, and the unwind values.
Failure patternsCommon Mistakes to Avoid
- Missing the base case.
- Not making progress toward the base case.
- Ignoring stack depth for deep inputs.
- Repeating subproblems without memoization when overlap exists.
- Forgetting cycle detection in graph-like data.
Execution guardrailQuick-Start Checklist
- Define base case.
- Define recursive case.
- Prove input gets smaller or progresses.
- State time and call-stack space.
- Check depth and cycle risks.
Recall drillKnowledge Check
| Question | Strong answer |
|---|---|
| What is a call frame? | One active function invocation stored on the call stack. |
| What is recursion space cost? | Usually maximum recursion depth. |
| When should recursion be avoided? | When input depth can exceed runtime stack limits or when iterative control is clearer. |
VocabularyKey Terms
| Term | Meaning |
|---|---|
| Base case | The condition that stops recursion. |
| Recursive case | The step that calls the function on a smaller subproblem. |
| Call stack | Runtime storage for active calls. |
| Stack overflow | Failure caused by too many nested calls. |
Next practiceFurther Reading
- Practice tree depth, tree inversion, and recursive DFS.
- Compare recursive DFS with explicit-stack DFS.
- Study memoization later for repeated recursive subproblems.