const solve = (nums) => { let left = 0, right = nums.length - 1; while (left < right) { const sum = nums[left] + nums[right]; if (sum === target) return [left, right]; }}
Study Guide

Recursion Guide for LeetCode: Build Recursive Thinking

Recursion is the foundation of trees, graphs, DP, and backtracking. If you struggle with recursion, every advanced pattern will feel impossible. Here is how to build recursive thinking from the ground up.

10 min read|

Recursion is the skill behind 60% of LeetCode problems

Trees, graphs, DP, backtracking — they all require recursive thinking

Recursion Is the Skill Behind 60% of LeetCode Problems

If there is one concept that separates beginners from intermediate LeetCode solvers, it is recursion. Trees, graphs, dynamic programming, backtracking, divide and conquer — they all depend on your ability to think recursively. You cannot avoid it.

The problem is that most people learn recursion through toy examples like computing factorials or Fibonacci numbers. Those examples teach you what recursion looks like, but they do not teach you how to think recursively. When you face a real LeetCode problem, the factorial mental model falls apart.

This guide teaches you a different approach. Instead of memorizing recursive patterns, you will learn a framework for breaking any problem into smaller subproblems, trusting that the function works for those subproblems, and combining the results. Once you internalize this framework, recursion stops being mysterious and starts being your most powerful tool.

Whether you are preparing for FAANG interviews or just starting your LeetCode journey, mastering recursion for interviews is the single highest-leverage skill you can develop. Everything else builds on top of it.

How Recursion Works — Base Case, Recursive Case, and the Call Stack

Every recursive function has two essential components: a base case that stops the recursion, and a recursive case that breaks the problem into smaller pieces. The base case is your exit condition — without it, your function calls itself forever and crashes with a stack overflow.

The recursive case is where the actual work happens. You take the current problem, reduce it by some amount, and call the same function on the smaller version. The call stack keeps track of where you are — each recursive call adds a new stack frame, and when a base case is reached, the frames start unwinding and returning results back up the chain.

Here is the mental model that makes recursion click: trust that the function works correctly for smaller inputs. You do not need to trace through every single call. If you can prove that your base case is correct and your recursive case correctly reduces the problem, the function will work. This is the recursive leap of faith, and it is the key to thinking recursively.

Think of it like managing a team. You do not do every task yourself — you delegate smaller tasks to your team members, trust they will handle them correctly, and then combine their results. Recursion works the same way: you handle the current level and delegate the rest.

The Recursion Template — A Skeleton for Every Recursive Problem

Every recursive solution follows the same skeleton, whether you are solving a tree traversal, a backtracking puzzle, or a divide-and-conquer problem. Once you internalize this recursion template, you have a starting point for any recursive problem on LeetCode.

Step one: define what the function returns. Before writing any code, decide what your recursive function should return for a given input. For a tree problem, it might return the height of a subtree. For a backtracking problem, it might return nothing but modify a results list. Being precise about the return value is half the battle.

Step two: handle the base case. Identify the smallest possible input and return the correct answer for it directly. For trees, the base case is usually a null node. For arrays, it is usually an empty array or a single element. The base case must not make any recursive calls.

Step three: make the recursive call. Call the function on a smaller version of the input. For trees, call on left and right children. For arrays, call on a subarray. Trust that these calls return the correct result — do not trace through them mentally.

Step four: combine the results. Take the values returned by your recursive calls and combine them to produce the answer for the current input. This is where the actual logic lives. For max depth, you take the max of left and right depths and add one. For merge sort, you merge two sorted halves.

  1. 1Define what the function returns for a given input
  2. 2Handle the base case — return the answer for the smallest input directly
  3. 3Make the recursive call on a smaller version of the problem
  4. 4Combine the results from recursive calls to answer the current problem
💡

Pro Tip

The key to recursion is trusting the function: assume it works correctly for smaller inputs, then focus only on how to combine those results for the current input. Don't trace through every call.

Recursion on Trees — The Most Natural Recursive Structure

Binary trees are the single best data structure for learning recursion. Every tree node naturally decomposes into a value, a left subtree, and a right subtree. The base case is always a null node. The recursive case always processes left and right children. Trees are recursion.

Consider LeetCode #104, Maximum Depth of Binary Tree. The recursive thinking is straightforward: the max depth of a tree is 1 plus the maximum of the depths of its left and right subtrees. The base case is that a null node has depth 0. That is the entire solution — two lines of actual logic.

LeetCode #100, Same Tree, follows the same pattern. Two trees are the same if their root values are equal and their left subtrees are the same and their right subtrees are the same. The base case handles null nodes: two nulls are the same, one null and one non-null are not.

LeetCode #226, Invert Binary Tree, is another classic. To invert a tree, swap the left and right children of the current node, then recursively invert the left and right subtrees. The base case is a null node, which stays null. Three lines of logic and you have solved a problem that famously stumped a Google interviewer.

If you are struggling with recursion on LeetCode, start with tree problems exclusively. Solve 10 to 15 easy tree problems and you will find that recursive thinking becomes second nature. The patterns transfer directly to graphs, backtracking, and DP.

  • LeetCode #104 — Maximum Depth of Binary Tree: depth = 1 + max(left depth, right depth)
  • LeetCode #100 — Same Tree: same if roots equal and both subtrees are same
  • LeetCode #226 — Invert Binary Tree: swap children, then recurse on both subtrees
  • LeetCode #112 — Path Sum: reduce target by current value, recurse on children
  • LeetCode #572 — Subtree of Another Tree: check if current matches or recurse on children

Recursion vs Iteration — When to Use Which Approach

A common interview follow-up is whether you can convert a recursive solution to an iterative one, or vice versa. Understanding when recursion vs iteration is the better choice shows depth of knowledge that interviewers value.

Every recursive algorithm can be converted to iteration using an explicit stack. This is because recursion itself uses the call stack — when you iterate with your own stack, you are doing the same thing manually. BFS with a queue and DFS with a stack are the classic examples.

Recursion is cleaner and more intuitive for tree traversals, divide-and-conquer algorithms like merge sort, and backtracking problems. When the problem has a natural recursive structure — where each subproblem looks like a smaller version of the original — recursion usually produces shorter and more readable code.

Iteration is better when you are worried about stack overflow on deep recursion, when tail-call optimization is needed, or when the problem has a straightforward linear structure like iterating through an array. Some languages do not optimize tail recursion, so deep recursive calls can crash.

In interviews, start with the recursive solution because it is usually easier to write correctly. If the interviewer asks about stack overflow or wants an iterative version, convert it using an explicit stack. Knowing both approaches and being able to switch between them is a strong signal.

  • Use recursion for trees, divide and conquer, and backtracking — the code is cleaner
  • Use iteration when recursion depth could exceed stack limits (very deep trees, large inputs)
  • Every recursive solution can be converted to iteration with an explicit stack
  • In interviews, write recursion first, then offer to convert if asked
ℹ️

Key Insight

Binary trees are the best data structure for learning recursion — every tree problem has a natural base case (null node) and recursive case (process left and right children)

Common Recursion Mistakes That Trip Up LeetCode Solvers

Understanding common recursion mistakes will save you from hours of debugging. These are the patterns that cause beginners to fail recursive problems even when they understand the high-level approach.

The most common mistake is a missing or incorrect base case. Without a proper base case, your function calls itself infinitely and you get a stack overflow. But an incorrect base case is even more insidious — your function terminates but returns wrong answers. Always verify your base case handles the smallest valid input correctly.

Another frequent error is returning the wrong type or forgetting to return at all. If your function should return an integer but one code path returns nothing, you will get subtle bugs. In recursive functions, every code path must return the expected type, including the base case.

Mutating shared state across recursive calls is a trap that catches even experienced programmers. If you pass a list by reference and modify it inside recursive calls, the modifications persist across calls in ways you might not expect. Either pass copies, or explicitly undo mutations when backtracking.

Finally, the biggest conceptual mistake is trying to trace through every recursive call mentally. This works for 2 or 3 levels of recursion, but it falls apart completely for real problems with 10 or 100 levels. You must learn to trust the recursive assumption: if the function works for smaller inputs, focus only on how to handle the current level.

  • Missing base case — causes infinite recursion and stack overflow
  • Incorrect base case — function terminates but returns wrong answers
  • Wrong return type — some code paths return nothing or the wrong type
  • Mutating shared state — modifications persist across calls unexpectedly
  • Mentally tracing every call — does not scale, trust the recursive assumption instead

Building Recursive Thinking — A Progression That Works

Recursive thinking is a skill you build through deliberate practice, not something you understand from reading a single article. Here is a concrete progression that takes you from beginner to confident recursive problem solver.

Start with binary tree problems. Trees have the most intuitive recursive structure and the clearest base cases. Solve LeetCode Easy tree problems like #104, #226, #100, #101, #111, and #112. For each one, explicitly identify the base case, the recursive calls, and how you combine results. Do not look at solutions until you have spent at least 15 minutes.

Next, move to backtracking problems. Backtracking is recursion with choices — at each step, you make a choice, recurse, and then undo the choice. Start with #78 Subsets, #46 Permutations, and #39 Combination Sum. The recursion template applies directly, with the addition of a choose-explore-unchoose pattern.

Then tackle dynamic programming as recursion plus memoization. Every DP problem can be solved recursively first, then optimized by caching results. Start with #70 Climbing Stairs and #198 House Robber as recursive solutions, then add memoization. This bridges the gap between recursion and DP naturally.

Throughout this progression, practice explaining your recursive solutions out loud. Say the base case, say what the recursive call returns, say how you combine results. If you can explain it clearly, you understand it. YeetCode flashcards are built around this exact practice — drilling the recursive structure of each problem until it becomes automatic.

The goal is not to memorize solutions. The goal is to train your brain to see recursive structure in new problems. Once you can look at a problem and instinctively decompose it into base case and recursive case, you have unlocked the most important skill in competitive programming and coding interviews.

  1. 1Start with Easy binary tree problems to build intuition for base cases and recursive calls
  2. 2Move to backtracking problems to learn recursion with choices and undoing
  3. 3Bridge to dynamic programming by solving DP problems recursively first, then adding memoization
  4. 4Practice explaining recursive solutions out loud — base case, recursive call, combination
  5. 5Use YeetCode flashcards to drill recursive patterns until they become automatic
⚠️

Common Pitfall

The #1 recursion mistake is trying to trace through every recursive call mentally — this doesn't scale past 3-4 levels. Instead, trust the function works for smaller inputs and focus on the current level

Ready to master algorithm patterns?

YeetCode flashcards help you build pattern recognition through active recall and spaced repetition.

Start practicing now