Recursion and Call Stack
Lesson 19Beginner50 minAssessment-backed

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

Explain recursion as solving a problem by delegating smaller subproblems.
Trace base cases, recursive cases, and call-stack frames.
Implement recursive traversal in Java, Python, and JavaScript.
Identify stack-overflow and repeated-work risks.
Know when an explicit stack or queue is safer than recursion.

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.

Recursive calls building and unwinding on the call stack
Each recursive call waits for smaller calls to finish. That waiting state consumes stack memory.

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.

QuestionRecursive answerRisk
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.
Tree recursion over folders and files
Tree-shaped data often fits recursion, but production inputs still require depth and cycle thinking.

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

CostMeaningWhat to state
TimeTotal work across all callsOften one call per node/item.
SpaceMaximum call-stack depthO(height) for tree recursion, O(n) worst case.
Repeated workSame subproblem solved many timesDynamic programming fixes this later.
Stack overflowToo many nested callsUse 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.

ExampleBrute-force approachStronger solutionProduction notes
Tree max depthManually track every path imperatively.Recursive depth from children plus one.Call-stack space is tree height.
Invert binary treeSwap one level only.Swap node children and recurse into subtrees.Base case handles null.
Deep graph DFSUse 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

QuestionStrong 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

TermMeaning
Base caseThe condition that stops recursion.
Recursive caseThe step that calls the function on a smaller subproblem.
Call stackRuntime storage for active calls.
Stack overflowFailure 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.