skip to content

questions

4

Tracing the call tree of a naive recursive Fibonacci, why does fib(6) take far more than 6 calls?

level: juniorimportance: must knowfreq 78%

answer

  1. Picture the shape the calls make
  2. One call, but two more from each
  3. Count nodes, not levels
  4. How many times does fib(2) appear?
  5. Twenty-five invocations for fib(6)

basics

~10 s

Every call spawns two more calls, so the calls form a branching tree rather than a straight chain. fib(6) expands into 25 invocations, and most of them recompute values the other branch already computed.

solid answer

~40 s

A recursion tree has one node per invocation, and its children are the calls that invocation makes. Naive Fibonacci calls itself on `n-1` and `n-2`, so each node has two children until it hits a base case — the shape is a bushy tree, not a line of 6 steps. Counting nodes for `fib(6)` gives 25 invocations. The counts per value are lopsided and repetitive: `fib(4)` is computed twice, `fib(3)` three times, `fib(2)` five times, `fib(1)` eight times. Depth and node count are different quantities — the deepest chain is only about 6 long, but the number of nodes grows exponentially in n. Confusing the two is the classic first mistake.

go deeper

for a junior

Be ready to draw the tree by hand for a small n and count the nodes out loud. Know that a node is one invocation and that the same argument can appear many times.

for a middle

Explain why the node count and the height are different quantities, and why two branches that shrink by different amounts produce a lopsided tree rather than a full one.

for a senior

Show that you use the drawing as a diagnostic: branching factor, argument shrinkage and repeated labels are three readings you take before you propose any fix.

for a principal

Own the framing that a hand-drawn tree is the cheapest cost model a team has. Know when the drawing is enough to decide and when a measurement is required instead.

## What a recursion tree is A recursion tree is a drawing of one particular execution. Each **node** is a single invocation, labelled by the arguments it was called with. Each **edge** points from an invocation to a call it makes. The root is the original call; the leaves are the invocations that return without recursing (the base cases). Nothing about the drawing is metaphorical: the node count is the number of invocations that actually happen, and the height is the length of the longest chain of nested calls. Drawing the tree is the standard way to answer "how expensive is this?" without any algebra. You count nodes; if each node does a constant amount of its own work, the node count *is* the running time. ## The naive Fibonacci tree The naive definition recurses on `n-1` and `n-2` and returns immediately for `n <= 1`. Expanding `fib(6)`: - `fib(6)` calls `fib(5)` and `fib(4)`. - `fib(5)` calls `fib(4)` and `fib(3)`. - `fib(4)` calls `fib(3)` and `fib(2)`. And so on. Count how many times each label appears in the whole tree: | label | times it appears | |---|---| | fib(6) | 1 | | fib(5) | 1 | | fib(4) | 2 | | fib(3) | 3 | | fib(2) | 5 | | fib(1) | 8 | | fib(0) | 5 | That totals **25 invocations** to produce one number. Two things jump out of the drawing. First, the repeats are not incidental — `fib(2)` really is computed five separate times, from scratch, each time. Second, the repeats concentrate near the bottom: the leaves are the most-duplicated labels, and the leaves are the bulk of the tree. ## Depth is not count The left-most spine (`fib(6) -> fib(5) -> fib(4) -> ... -> fib(1)`) has about n links, so the tree's **height** is about n. That is the quantity people reach for when they say "it recurses n times". But the height counts one path; the cost counts every node on every path. In a tree where each node has two children, the number of nodes grows multiplicatively with height, not additively. Saying "it goes six deep, so six calls" silently assumes the tree is a chain — true for a single-call recursion, false the moment a second recursive call appears. ## Why the tree is lopsided This particular tree is not a perfect binary tree, because the two children shrink by different amounts: one branch drops by 1, the other by 2, so the `n-2` side bottoms out sooner and its subtree is smaller. That is why the totals follow the Fibonacci numbers themselves rather than powers of two, and why the growth rate is roughly 1.618 to the n rather than 2 to the n. It is still exponential — but a candidate who asserts "exactly 2^n calls" has drawn a tree that is not this one. ## What the drawing is worth in an interview The drawing answers three questions at once, and you should say all three out loud while you draw: 1. **How does it branch?** Two children per node here, so the width multiplies as you descend. 2. **How fast do arguments shrink?** By 1 and by 2, so the tree is deep — about n levels. (Compare a recursion that halves its argument: only about log n levels, a completely different shape.) 3. **Do labels repeat?** Yes, heavily — circle two nodes carrying the same label and note that their subtrees are byte-for-byte identical work. Those three observations are what an interviewer is listening for. The exponential blow-up is the consequence of the first two; the third is the observation that opens the door to computing each label once instead of many times. ## Common traps - **Counting levels instead of nodes.** Height and work are different quantities. - **Assuming the runtime remembers.** Nothing caches the repeated calls for you; `fib(2)` is recomputed every one of its five appearances. - **Assuming a perfect binary tree.** Levels are not uniformly full when the two branches shrink by different amounts. - **Stopping at "it's slow".** The interviewer wants the shape — branching factor, depth, repetition — not an adjective.

  • How deep does that tree get, and why isn't the depth the same as the call count?
    The longest chain follows the `n-1` branch all the way down, so the height is about n. The call count is the number of nodes across every path, and with two children per node that grows multiplicatively as you descend. Height answers "how nested does it get"; node count answers "how much work happens". They only coincide when each node has a single child.
  • Which values get recomputed most in the fib(6) tree, and where do they sit?
    The small ones, near the leaves: `fib(1)` appears eight times and `fib(2)` five times, while `fib(5)` appears once. Duplication grows as you descend because more distinct paths funnel into the same small arguments. That is also why the tree's cost is dominated by its bottom levels — the leaves outnumber everything above them.
  • If you circle two nodes with the same label, what can you say about their subtrees?
    They are identical, top to bottom — same shape, same node count, same result. The invocation's behaviour depends only on its argument, so equal labels mean the whole subtree below is duplicated work. Noticing that on the whiteboard is the moment you can say out loud that each distinct label only ever needs to be computed once.

It is less like walking down six stairs and more like a rumour where every person tells two others: the same small piece of gossip reaches the bottom over and over.

saying these in an interview costs you the question

  • Says it recurses n times, so about n calls
  • Reports the tree's depth when asked for the call count
  • Assumes repeated calls are cached automatically
  • Claims the tree is a perfect binary tree with 2^n nodes
  • Cannot say what a node in the drawing represents

context

open as a page

Why is a function making two recursive calls on n-1 exponential rather than O(n^2)?

level: middleimportance: must knowfreq 70%

basics

~20 s

Two calls per invocation multiply the width of the tree at every level, so the node count doubles level by level and reaches about 2^n over n levels. Multiplying once per level is exponential; O(n^2) would need the work to merely add up.

open as a page

In a game-move tree with 3 legal moves per position, what does searching one ply deeper cost?

level: middleimportance: should knowfreq 48%

basics

~20 s

One extra ply multiplies the whole search by about three: each position at the current frontier fans out into three more. Depth-limited search cost is dominated by the deepest level, so deepening is a multiplication, never an increment.

open as a page

In a drawn game-search tree, how do you tell that different move orders re-explore the same position?

level: seniorimportance: should knowfreq 56%

basics

~20 s

Label every node with the arguments the invocation received — the position and the remaining depth — instead of with the move that led there. Repeated labels are repeated work: identical labels have identical subtrees beneath them.

open as a page