Pattern #20

Recursion

Important interview questions, thinking patterns, base cases, call stack mechanics, and rules for solving recursive problems in Go.

Must Solve

18 core questions — solve these first.

  1. 1.Factorial
    easy
  2. 2.Fibonacci Number
    easy
  3. 3.Pow(x, n)
    medium
  4. 4.Reverse String
    easy
  5. 5.Palindrome Check
    easy
  6. 6.Binary Search using Recursion
    easy
  7. 7.Merge Two Sorted Lists
    easy
  8. 8.Reverse Linked List
    easy
  9. 9.Maximum Depth of Binary Tree
    easy
  10. 10.Same Tree
    easy
  11. 11.Invert Binary Tree
    easy
  12. 12.Path Sum
    easy
  13. 13.Generate Parentheses
    medium
  14. 14.Subsets
    medium
  15. 15.Permutations
    medium
  16. 16.Combination Sum
    medium
  17. 17.Letter Combinations of a Phone Number
    medium
  18. 18.Word Search
    medium

Also Important

9 more questions worth practicing.

  1. 19.Climbing Stairs
    easy
  2. 20.K-th Symbol in Grammar
    medium
  3. 21.Swap Nodes in Pairs
    medium
  4. 22.Decode String
    medium
  5. 23.Different Ways to Add Parentheses
    medium
  6. 24.Unique Paths
    medium
  7. 25.N-Queens
    hard
  8. 26.Sudoku Solver
    hard
  9. 27.Tower of Hanoi
    medium

How to Think

  1. Can problem become a smaller same problem?Recursion
  2. Tree problem?Recursion
  3. Need try all choices?Recursion + Backtracking
  4. Need divide problem into smaller parts?Recursion (Divide & Conquer)
  5. Same work repeats many times?Recursion + Memoization

Recursive Thinking Template & Go Example

3 Golden Questions for Every Recursive Function:

  1. What does my function mean? (e.g. maxDepth(node))
  2. What is the smallest / Base Case? (node == nil -> 0)
  3. How do I reduce the problem? (1 + max(left, right))
func maxDepth(root *TreeNode) int {
    // 1. Base Case (stops recursion)
    if root == nil {
        return 0
    }

    // 2. Reduce Problem (subproblems for left & right children)
    leftDepth := maxDepth(root.Left)
    rightDepth := maxDepth(root.Right)

    // 3. Return answer back upward
    return 1 + max(leftDepth, rightDepth)
}

👉 Calls go DOWN call stack → Answers return UPWARD

Two Essentials Every Recursion Needs

1. Base Case
if n <= 1 { return 1 }

Stops recursion. Without a base case, the function calls itself infinitely until stack overflow crash!

2. Smaller Problem
factorial(n) -> factorial(n-1)

Each recursive call must move strictly closer toward the stopping base case.

Recursion vs Iteration

Recursion calls itself (using the call stack), while iteration uses explicit loops (for / while).

Use Recursion when problem structure is naturally recursive:

Binary TreesGraph DFSBacktrackingDivide & Conquer
Visual Memory Rule
Call  →  Smaller Problem  →  Base Case  →  Return Answer Upward
Tree/DFS     →  Recursion
All choices  →  Recursion + Backtracking
Repeated     →  Memoization

💡 Golden Rule: "Define what one recursive call should solve, make the problem smaller, and trust the next call to solve the rest."

Common Interview Mistakes

1. Missing Base Case

Forgetting base case condition leads directly to infinite recursion and stack overflow crashes!

2. Base Case Checked Too Late

Dereferencing node fields (node.Val) before checking node == nil causes null pointer panics.

3. Forgetting Return Value

Calling dfs(child) without saving or returning its result ignores critical subproblem answers.

4. Ignoring Call Stack Space

Recursion uses implicit call stack space (O(depth)) even without allocating explicit arrays.

Interview Rules

  1. 1. Tree problem? → Think Recursion
  2. 2. DFS traversal? → Recursion fits naturally
  3. 3. Try every choice? → Recursion + Backtracking
  4. 4. Base case required first to specify stopping condition
  5. 5. Every call must reduce problem size toward base case
  6. 6. Call stack space = O(recursion depth)
  7. 7. Deep recursion risk → Watch out for stack overflow on massive inputs
  8. 8. Repeated subproblems? → Use Memoization cache
  9. 9. Multiple branching calls (e.g. fib(n-1) + fib(n-2)) → Watch out for exponential time O(2^N)

Small Rules

  1. Rule 1: Always find and write the base case first.
  2. Rule 2: Each call must move strictly toward stopping (e.g. n-1).
  3. Rule 3: Recursion implicitly consumes O(depth) memory on call stack.
  4. Rule 4: Two branching calls without memoization cause O(2^N) exponential explosion.
  5. Rule 5: Always calculate the total number of function calls to determine time complexity.

Production Thinking

Nested Folder TraversalVisit directory & recursively process nested subfolders

JSON / AST ParsingTraverse arbitrarily nested JSON objects & abstract syntax trees

UI Component TreesReact Virtual DOM rendering & event bubbling up component tree

Package Dependency ResolutionWalk package dependency trees with cycle detection guard

Production Stack Overflow SafetyPrefer iterative loops for extremely deep structures (millions of items)

Remember This

Recursion            → function calls itself
Must have            → base case
Each call            → smaller problem
Calls                → go down
Answers              → come back up
Tree / DFS           → recursion
All choices          → recursion + backtracking
Repeated work        → memoization
Very deep calls      → stack risk

💡 Golden Rule: "Define what one recursive call should solve, make the problem smaller, and trust the next call to solve the rest."