datarekha

Recursion & Tracing

A function that calls itself on a smaller input until a base case fires. The GATE DA skill is tracing the call tree and counting calls — including over dict-encoded trees.

8 min read Intermediate GATE DA Lesson 50 of 122

What you'll learn

  • A recursive function calls itself on a smaller input until a base case stops it
  • Tracing recursion: expand the call tree, then combine return values as the calls unwind
  • Recursion over lists and over dict-encoded trees — a common GATE DA framing
  • Counting the number of recursive calls a function makes

Before you start

A recursive function solves a problem by calling itself on a smaller version of the same problem — and stops when the input is small enough to answer directly. That stopping point is the base case. GATE DA rarely asks you to invent recursion; it asks you to trace it: given the code and an input, what does it return, and how many calls does it make? The same tree-walking pattern is everywhere in real data work — parsing nested JSON, traversing a file system, or scoring a decision tree all lean on exactly this.

The two parts of every recursion

  1. Base case — the input is small enough to answer with no further calls.
  2. Recursive case — shrink the input toward the base case and call yourself.

The classic example is factorial:

def fact(n):
    if n <= 1:          # base case
        return 1
    return n * fact(n - 1)   # recursive case: n shrinks by 1

fact(4) calls fact(3), which calls fact(2), which calls fact(1). At n = 1 the base case fires and returns 1. Then the answers combine on the way back up as each call finishes: 1 → 2 → 6 → 24.

Trace by expanding the call tree

The reliable way to trace recursion: draw the calls as a tree, push down to the base cases, then combine the returns as they bubble up. Step through this stack growing one frame per call and shrinking one frame per return:

The single most important habit: the result is built as the calls UNWIND. Nothing is “added up” on the way down — each call just spawns smaller calls. The combining (n * ..., or summing children) happens on the way back, when each call has its children’s answers in hand.

Recursion over a dict-encoded tree

GATE DA likes to encode a tree as a dictionary mapping each node to its list of children, then ask you to recurse over it. Here a node has no children when its list is empty — that empty list is the base case (the sum over no children is 0).

01234leaves (2,3,4) have no children → return 1
tree = {0: [1, 2], 1: [3, 4], 2: [], 3: [], 4: []} — counting every node gives 5.

Each call returns 1 for itself plus the counts of all its children. The combining happens as the recursion unwinds — leaves return 1, internal nodes add their children’s totals.

Trace it: count(0) = 1 + count(1) + count(2). count(2) = 1 (empty children). count(1) = 1 + count(3) + count(4) = 1 + 1 + 1 = 3. So count(0) = 1 + 3 + 1 = 5. Notice each of the 5 nodes is visited exactly once, so the function also makes 5 calls — one per node.

How GATE asks this

A 2024 question gave exactly this style: a tree encoded as a dict of children and a near-identical count-style recursion, and asked for the returned node count (its larger tree counted to 9). The same paper also showed a recursive in-place swap that reverses a list segment — swap a[i] with a[j], then recurse inward on (i+1, j-1) until the indices meet:

def rev(a, i, j):
    if i >= j:               # base case: pointers met or crossed
        return
    a[i], a[j] = a[j], a[i]  # swap the ends
    rev(a, i + 1, j - 1)     # recurse on the inner segment

a = [1, 2, 3, 4, 5]
rev(a, 0, 4)                 # a becomes [5, 4, 3, 2, 1]

The pattern is always: identify the base case, then hand-expand the calls and combine returns as they unwind. For a counting question, count one call per node/element the recursion touches.

Quick check

Quick check

0/6
Q1For tree = {0: [1, 2], 1: [3, 4], 2: [], 3: [], 4: []} and the function count(t, node) = 1 + sum(count(t, c) for c in t[node]), what does count(tree, 0) return?numerical answer — type a number
Q2Trace this function: def f(n): if n <= 0: return 1; else: return 2 * f(n - 1). What is f(5)?numerical answer — type a number
Q3def dsum(n): if n == 0: return 0; else: return n % 10 + dsum(n // 10). What does dsum(1234) return?numerical answer — type a number
Q4How many calls (including the first) does count(tree, 0) make for the 5-node tree above?numerical answer — type a number
Q5Which statements about recursion are TRUE? (select all that apply)select all that apply
Q6A recursion reverses a list segment in place: swap a[i] and a[j], then recurse on (i+1, j-1) until i >= j. Starting from a = [1, 2, 3, 4, 5] with rev(a, 0, 4), what is a[0] after it finishes?numerical answer — type a number

Practice this in an interview

All questions

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Explore further

Related lessons

Skip to content