Quiz 2

Week 9: Recursion

1560 words
8 min read
Python Week 1: the first filter for runtime behavior
Visual companion
Python
Type and operator map

Python Week 1: the first filter for runtime behavior

View
Revision summary

What this note is really saying

Short form

# Week 9: Recursion > **BSCS1001 — IIT Madras BS Degree** **Prerequisite:** Week 3 (Procedures), Week 5 (Lists) **Cross-links:** BSCS1002-Python (Week 10 — Recursion), BSCS2002-PDSA (Week 9 — Recursion) ## 1. Motivation: Why Recursion?

Week 9: Recursion

BSCS1001 — IIT Madras BS Degree Prerequisite: Week 3 (Procedures), Week 5 (Lists) Cross-links: BSCS1002-Python (Week 10 — Recursion), BSCS2002-PDSA (Week 9 — Recursion)

1. Motivation: Why Recursion?

Some problems have a natural structure where the solution to a big problem depends on solving a smaller version of the same problem.
ProblemBig VersionSmaller Version
Factorial5! = 5 × 4 × 3 × 2 × 14! = 4 × 3 × 2 × 1
Sum of list[1,2,3] sum = 1 + rest[2,3] sum
DFS on graphExplore all neighborsExplore one neighbor's neighbors
Insertion sortSort N elementsSort N-1 elements, then insert last
Real-world analogy: Russian nesting dolls (matryoshka). To open the largest doll, you recursively open smaller and smaller dolls until you reach the smallest one, then build back up.

2. What is Recursion?

Recursion is when a procedure calls itself. (Diagram)

Two Essential Parts

Every recursive procedure must have:
  1. Base case: A simple version that can be solved directly (no recursion)
  2. Recursive case: A version that calls itself with smaller input
💡 Key Insight: If there's no base case, the recursion never stops (infinite recursion). If the recursive case doesn't reduce the problem size, it also never stops.

3. Anatomy of a Recursive Procedure

Template

pseudo
Procedure RecursiveFunction(input)
    // Base case
    if (base condition) {
        return(simple value)
    }
    // Recursive case
    else {
        smallerInput = reduce(input)
        partialResult = RecursiveFunction(smallerInput)
        result = combine(partialResult, input)
        return(result)
    }
End RecursiveFunction

The Three Questions

QuestionAnswerExample (Factorial)
What is the base case?Smallest input we can solve directlyn = 0
What is the base value?Answer for base case1
How do we reduce?Make input smallern → n-1
How do we combine?Use result of smaller to solve largern × factorial(n-1)

4. Factorial: The Classic Example

Mathematical Definition

pseudo
n! = n × (n-1) × (n-2) × ... × 2 × 1
0! = 1  (by definition)

Recursive Definition

pseudo
factorial(0) = 1                    // Base case
factorial(n) = n × factorial(n-1)   // Recursive case (for n > 0)

Pseudocode

pseudo
Procedure Factorial(n)
    if (n == 0) {
        return(1)
    }
    else {
        return(n * Factorial(n-1))
    }
End Factorial

Tracing Factorial(4)

(Diagram)

Tracing Table

CallInputChecks Base?Recursive CallReturns
Factorial(4)4No (4≠0)4 × Factorial(3)4 × 6 = 24
Factorial(3)3No3 × Factorial(2)3 × 2 = 6
Factorial(2)2No2 × Factorial(1)2 × 1 = 2
Factorial(1)1No1 × Factorial(0)1 × 1 = 1
Factorial(0)0Yes!(none)1

5. Tracing Recursion: The Call Stack

What Happens in Memory

When Factorial(4) calls Factorial(3), the computer:
  1. Suspends Factorial(4) — remembers where it was and its variables
  2. Starts Factorial(3) on top of it
  3. This continues until Factorial(0) returns
  4. Then each suspended call resumes in reverse order

The Call Stack

sql
Step 1: Factorial(4) called
Stack: [Factorial(4)]
Step 2: Factorial(4) calls Factorial(3)
Stack: [Factorial(4), Factorial(3)]
Step 3: Factorial(3) calls Factorial(2)
Stack: [Factorial(4), Factorial(3), Factorial(2)]
Step 4: Factorial(2) calls Factorial(1)
Stack: [..., Factorial(2), Factorial(1)]
Step 5: Factorial(1) calls Factorial(0)
Stack: [..., Factorial(1), Factorial(0)]
Step 6: Factorial(0) returns 1 — POPS from stack
Stack: [..., Factorial(1)]
Step 7: Factorial(1) computes 1*1 = 1 — POPS
Stack: [..., Factorial(2)]
Step 8: Factorial(2) computes 2*1 = 2 — POPS
Stack: [..., Factorial(3)]
Step 9: Factorial(3) computes 3*2 = 6 — POPS
Stack: [Factorial(4)]
Step 10: Factorial(4) computes 4*6 = 24 — POPS
Stack: [] (empty)

6. Recursion on Lists

Sum of List Elements

pseudo
Procedure ListSum(L)
    if (L == []) {
        return(0)                    // Base: empty list sum = 0
    }
    else {
        return(first(L) + ListSum(rest(L)))  // First + sum of rest
    }
End ListSum

Tracing: ListSum([1, 3, 5])

CallLBase?first(L) + ListSum(rest)Result
ListSum([1,3,5])[1,3,5]No1 + ListSum([3,5])1+8=9
ListSum([3,5])[3,5]No3 + ListSum([5])3+5=8
ListSum([5])[5]No5 + ListSum([])5+0=5
ListSum([])[]Yes0 (base)0

Length of List

pseudo
Procedure ListLength(L)
    if (L == []) {
        return(0)
    }
    else {
        return(1 + ListLength(rest(L)))
    }
End ListLength

7. Recursive Insertion Sort

Insertion sort can be defined recursively:

Recursive Definition

  • Base case: A list of length ≤ 1 is already sorted
  • Recursive case: Sort rest(L), then insert first(L) into the sorted rest

Pseudocode

pseudo
Procedure InsertionSortRec(L)
    if (length(L) <= 1) {
        return(L)
    }
    else {
        sortedRest = InsertionSortRec(rest(L))
        return(SortedListInsert(sortedRest, first(L)))
    }
End InsertionSortRec

Tracing: InsertionSortRec([3, 1, 4])

CallLBase?sortedRestInsert first(L) into sortedRestResult
ISR([3,1,4])[3,1,4]NoISR([1,4]) → [1,4]Insert 3 → [1,3,4][1,3,4]
ISR([1,4])[1,4]NoISR([4]) → [4]Insert 1 → [1,4][1,4]
ISR([4])[4]Yes[4]

8. Recursion vs Iteration

AspectIterationRecursion
MechanismLoop (while, foreach)Self-calling procedure
StateExplicit variablesImplicit (call stack)
TerminationCondition becomes falseBase case reached
PerformanceGenerally fasterSlightly slower (call overhead)
MemoryLess (fixed variables)More (call stack grows)
Natural forSequential processingHierarchical/inductive problems
RiskInfinite loopStack overflow (infinite recursion)

When to Use Recursion

(Diagram)

9. Practice Questions

Basic Questions

Q1. What are the two essential parts of a recursive procedure?
Show Answer
  1. Base case: A simple input that can be solved directly (no recursion)
  2. Recursive case: Calls itself with a smaller/ simpler input Q2. Trace Factorial(3) showing all recursive calls and returns. Show Answer
CallnBase?ActionReturns
Factorial(3)3No3 × Factorial(2)6
Factorial(2)2No2 × Factorial(1)2
Factorial(1)1No1 × Factorial(0)1
Factorial(0)0YesReturn 11
Final result: 6 Q3. Write a recursive procedure to compute the sum of integers from 1 to n. Show Answer
pseudo
Procedure SumToN(n)
    if (n == 0) {
        return(0)
    }
    else {
        return(n + SumToN(n-1))
    }
End SumToN
Q4. What happens if a recursive procedure has no base case?
Show Answer
It results in infinite recursion — the procedure calls itself forever, never returning. This would eventually cause a stack overflow (the call stack runs out of memory).

Intermediate Questions

Q5. Trace ListLength([10, 20, 30, 40]).
Show Answer
CallLBase?Returns
LL([10,20,30,40])[10,20,30,40]No1 + LL([20,30,40]) = 4
LL([20,30,40])[20,30,40]No1 + LL([30,40]) = 3
LL([30,40])[30,40]No1 + LL([40]) = 2
LL([40])[40]No1 + LL([]) = 1
LL([])[]Yes0
Final result: 4 Q6. Write a recursive procedure to find the maximum element in a list. Show Answer
pseudo
Procedure MaxList(L)
    if (length(L) == 1) {
        return(first(L))                     // Only one element
    }
    else {
        maxOfRest = MaxList(rest(L))
        if (first(L) > maxOfRest) {
            return(first(L))
        }
        else {
            return(maxOfRest)
        }
    }
End MaxList
Q7. Compare recursion and iteration. Give one advantage of each.
Show Answer
  • Advantage of recursion: More natural for problems with self-similar structure (factorial, tree traversal, DFS). Code is often more elegant and readable.
  • Advantage of iteration: Generally faster, uses less memory (no call stack), and is simpler for straightforward repetitive tasks.
Trade-off: Elegance vs efficiency. Q8. What is the call stack? Why is it important for recursion? Show Answer
The call stack is a data structure that tracks all active (suspended) procedure calls. When a procedure calls another, the current state is pushed onto the stack. When the called procedure returns, the previous state is popped.
For recursion, the call stack is essential because each recursive call suspends the current computation. Without it, the computer couldn't "remember" where to resume after the recursive call returns.

Advanced Questions

Q9. Trace the recursive insertion sort for [4, 2, 5].
Show Answer
CallLBase?sortedRestInsert firstResult
ISR([4,2,5])[4,2,5]No[2,4,5]Insert 4 → [2,4,5][2,4,5]
ISR([2,5])[2,5]No[5]Insert 2 → [2,5][2,5]
ISR([5])[5]Yes[5]
Final: [2, 4, 5] Q10. Write a recursive procedure to check if a value x is present in a list. Show Answer
pseudo
Procedure IsMember(x, L)
    if (L == []) {
        return(False)                 // Not found
    }
    else if (first(L) == x) {
        return(True)                  // Found!
    }
    else {
        return(IsMember(x, rest(L)))  // Search rest
    }
End IsMember
Q11. Why does the recursive case need to reduce the problem size? What happens if it doesn't?
Show Answer
The recursive case MUST reduce the problem size (move toward the base case) to ensure termination. If it doesn't:
  • The procedure would call itself with the same (or larger) input forever
  • The base case would never be reached
  • This results in infinite recursion → stack overflow
Example of WRONG factorial:
pseudo
Procedure BadFactorial(n)
    if (n == 0) {
        return(1)
    }
    else {
        return(n * BadFactorial(n))   // n doesn't decrease!
    }
End BadFactorial
This never reaches n=0 and runs forever. Q12. A recursive procedure has a "premature" base case. What would happen if Factorial's base case was n=1 instead of n=0? Show Answer
If Factorial(0) is called:
  • Base case is n=1 → not reached
  • Recursive case: n=0 → calls Factorial(-1)
  • Factorial(-1): calls Factorial(-2)
  • ... never reaches 1, runs forever
The original definition with base case n=0 is correct because factorials are defined for non-negative integers, and 0! = 1.

📚 Cross-References

CourseTopicConnection
BSCS1002 (Python)Week 10 — RecursionPython recursive functions
BSCS2002 (PDSA)Week 9 — RecursionRecursion tree, tail recursion
BSCS2002 (PDSA)Week 10 — Divide & ConquerRecursive problem solving

Quiz Tip: Recursion tracing questions are common. Practice drawing the call stack! Join Discord PreviousGraph Algorithms — Routes & PathsNextDepth-First Search (DFS)
Document outline

Keep your place and jump directly to a heading.

Table of Contents
System Normal // Awaiting Context

Intelligence Hub

Navigate the knowledge graph to generate context. The Hub adapts dynamically to surface backlinks, related notes, and metadata insights.