CMD Guide
HomeDSARecursion

Complexity Analysis

A recursive algorithm's running time is governed by a recurrence relation — T(n) expressed in terms of T applied to smaller inputs — and solving that recurrence, not eyeballing the code, is what yields the true asymptotic bound, because recursive cost stacks non-linearly across levels of self-similar subcalls.

Recognize the pattern

The recurrence relation

General form: T(n) = a·T(n/b) + f(n), where a is the number of subproblems per call, n/b is the size of each subproblem, and f(n) is the work done outside the recursive calls (dividing input + combining results). The base case, e.g. T(1) = Θ(1), is where recursion bottoms out.

Example: merge sort splits an array into 2 halves and spends O(n) merging them → T(n) = 2T(n/2) + O(n).

Brute force vs. optimal derivation

Brute force (manual unrolling): expand T(n) → T(n/2) → T(n/4) … term by term until a pattern emerges, then sum the resulting series. It always works but is slow, error-prone on depth/off-by-one, and impractical for anything with an ugly f(n).

Optimal — pick the matching technique:

TechniqueBest forCost to apply
Recursion treeVisual intuition, uneven subproblem sizes, verifying a guessO(depth) drawing effort; error-prone for irregular trees
SubstitutionProving a guessed bound rigorously (induction)Requires a good initial guess; induction step can be fiddly
Master theoremT(n) = aT(n/b) + f(n) in standard formO(1) lookup once the three cases are memorized

Complexity derived from first principles

Take T(n) = 2T(n/2) + cn (merge sort). Build the recursion tree and count total work level by level:

Total time = (work per level) × (number of levels) = cn · log2(n) = Θ(n log n). This matches Master Theorem Case 2 (a=2, b=2, f(n)=Θ(nlog_b a) = Θ(n1)).

Space is a separate axis: it is the max depth of the call stack × space per frame, not the total nodes in the tree. Merge sort's deepest single active path is O(log n) frames, but each merge step also allocates O(n) auxiliary array space at various points — net auxiliary space is O(n) (dominated by the merge buffers), call-stack space is O(log n).

Traced worked example

T(n) = 2T(n/2) + n, with n = 8 (using c = 1 for simplicity):

Level i# nodessize of eachcost per nodelevel total
01888
12448
24228
3 (base)8118

Depth = log2(8) = 3 → 4 levels (0..3). Total = 8 × 4 = 32 = n·(log2 n + 1), confirming Θ(n log n).

Pitfalls

When to use which technique

Master theorem: fastest when the recurrence is already in aT(n/b)+f(n) form and one of the three cases cleanly applies — O(1) to apply, but doesn't cover unequal subproblem sizes or non-polynomial gaps.

Recursion tree: use when subproblem sizes are unequal (e.g. T(n)=T(n/3)+T(2n/3)+n) or you need intuition/a guess to verify — more visual but more manual bookkeeping.

Substitution (induction): use when you already suspect a bound and need a rigorous proof, or the recurrence has extra terms Master Theorem can't handle — most rigorous but requires a correct guess up front.

Trade-off in one line: Master theorem trades generality for speed; recursion tree and substitution trade speed for generality and rigor.

Recurrence shapes worth memorizing: T(n)=T(n-1)+O(1) → Θ(n) time and Θ(n) stack (linear recursion); T(n)=T(n-1)+O(n) → Θ(n²) (quicksort worst case); T(n)=T(n/2)+O(1) → Θ(log n) (binary search); T(n)=2T(n/2)+O(n) → Θ(n log n) (merge sort); T(n)=T(n-1)+T(n-2)+O(1) → Θ(φn) time with Θ(n) stack (naive Fibonacci — the left spine, not the node count, sets the depth).

Takeaways

Recall: For T(n) = 3T(n/2) + n, what is the per-level work at level i, and what is the overall time complexity?


Synthesized from standard recurrence-analysis treatments (CLRS Master Theorem & recursion-tree method) and the source page's recursion tree walkthrough.

🤖 Don't fully get this? Learn it with Claude

Stuck on Complexity Analysis? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Complexity Analysis** (DSA) and want to truly understand it. Explain Complexity Analysis from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Complexity Analysis** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Complexity Analysis** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Complexity Analysis** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes