Recursion Concept and Call Stack Visualization in DSA Typescript - Time & Space Complexity
When using recursion, it is important to understand how many times the function calls itself.
We want to know how the number of calls grows as the input size increases.
Analyze the time complexity of the following recursive function.
function factorial(n: number): number {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
This function calculates the factorial of a number by calling itself with a smaller number until it reaches 1.
Look at what repeats in this code:
- Primary operation: The function calls itself once each time with n reduced by 1.
- How many times: It repeats until n reaches 1, so about n times.
Each increase in n adds one more function call.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 calls |
| 100 | 100 calls |
| 1000 | 1000 calls |
Pattern observation: The number of calls grows directly with n, so it grows in a straight line.
Time Complexity: O(n)
This means the time taken grows in direct proportion to the input size.
[X] Wrong: "Recursion always makes the program slow and complex because it repeats too much."
[OK] Correct: Recursion can be simple and efficient if each call does a small, fixed amount of work and the number of calls grows linearly.
Understanding recursion and its time cost helps you explain your solutions clearly and shows you can reason about how your code behaves as inputs grow.
"What if the recursive function called itself twice each time? How would the time complexity change?"
Practice
Solution
Step 1: Understand recursion stopping condition
A recursive function must have a base case to stop calling itself; otherwise, it keeps calling endlessly.Step 2: Effect of missing stopping condition
Without a stopping condition, the function calls stack up until memory runs out, causing a stack overflow error.Final Answer:
It causes an infinite loop leading to a stack overflow error -> Option BQuick Check:
Missing base case = infinite recursion [OK]
- Assuming recursion stops automatically
- Confusing infinite loop with syntax error
- Thinking recursion runs only once without base case
Solution
Step 1: Check for base case and recursive call
function recurse(n: number): number { if (n <= 0) return 0; return n + recurse(n - 1); } has a base case (n <= 0) and calls itself with n - 1, which is correct for recursion.Step 2: Analyze other options for errors
The version with a while loop lacks a proper base case and return statement; another calls recurse with n + 1 causing infinite recursion; another calls recurse with the same n causing infinite recursion.Final Answer:
function recurse(n: number): number { if (n <= 0) return 0; return n + recurse(n - 1); } -> Option AQuick Check:
Base case + decreasing argument = correct recursion [OK]
- Missing base case
- Increasing argument causing infinite recursion
- Using loops instead of recursion
function factorial(n: number): number {
if (n === 0) return 1;
return n * factorial(n - 1);
}
console.log(factorial(3));Solution
Step 1: Trace factorial calls
factorial(3) calls factorial(2), factorial(2) calls factorial(1), factorial(1) calls factorial(0) which returns 1.Step 2: Calculate return values
factorial(1) = 1 * 1 = 1; factorial(2) = 2 * 1 = 2; factorial(3) = 3 * 2 = 6.Final Answer:
6 -> Option DQuick Check:
3! = 6 [OK]
- Confusing factorial with sum
- Not tracing base case return
- Multiplying incorrectly
function sumTo(n: number): number {
return n + sumTo(n - 1);
}Solution
Step 1: Identify missing base case
The function lacks a stopping condition, so it will recurse infinitely causing stack overflow.Step 2: Fix by adding base case
Adding if (n <= 0) return 0; stops recursion when n reaches 0 or less.Final Answer:
Add a base case: if (n <= 0) return 0; -> Option CQuick Check:
Base case needed to stop recursion [OK]
- Ignoring base case causes infinite recursion
- Changing recursive call incorrectly
- Removing recursion defeats purpose
printNumbers(3)? Visualize the call stack.function printNumbers(n: number): void {
if (n === 0) return;
printNumbers(n - 1);
console.log(n);
}Solution
Step 1: Understand call stack order
printNumbers(3) calls printNumbers(2), which calls printNumbers(1), which calls printNumbers(0) and returns immediately.Step 2: Trace console.log calls after recursion
After reaching base case, console.log prints 1, then 2, then 3 as the stack unwinds.Final Answer:
1 2 3 -> Option AQuick Check:
Post-recursion print = ascending order [OK]
- Printing before recursion causes descending order
- Confusing call stack push/pop order
- Expecting repeated numbers
Ready to prove it?
Pass the test and this pattern moves unknown
