Why Recursion Exists and What Loops Cannot Express Cleanly in DSA Typescript - Performance Analysis
We explore why recursion is useful and how it differs from loops in expressing repeated tasks.
We want to understand how the time cost grows when using recursion compared to loops.
Analyze the time complexity of this recursive function that calculates factorial.
function factorial(n: number): number {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
This function calls itself to multiply numbers from n down to 1.
Look for repeated actions in the code.
- Primary operation: Recursive call to factorial with n-1.
- How many times: Exactly n times until base case (n=1) is reached.
Each call waits for the next call to finish, so the total steps grow with n.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 multiplications and calls |
| 100 | 100 multiplications and calls |
| 1000 | 1000 multiplications and calls |
Pattern observation: The number of operations grows directly with n, linearly.
Time Complexity: O(n)
This means the time to complete grows in a straight line as n gets bigger.
[X] Wrong: "Recursion always takes more time than loops."
[OK] Correct: Both recursion and loops can do the same number of steps; recursion just expresses the steps differently.
Understanding recursion's time cost helps you explain your choices clearly and shows you know when recursion is a good fit.
"What if the factorial function used a loop instead of recursion? How would the time complexity change?"
Practice
Solution
Step 1: Understand recursion's nature
Recursion breaks a problem into smaller versions of itself, which loops cannot express naturally.Step 2: Compare loops and recursion
Loops repeat fixed steps but cannot easily handle problems defined by self-similar subproblems like tree traversals.Final Answer:
Because recursion can express problems with self-similar subproblems naturally -> Option AQuick Check:
Recursion = self-similar problem solving [OK]
- Thinking loops are always faster
- Believing recursion always uses less memory
- Assuming loops cannot run many times
Solution
Step 1: Identify recursive call
function factorial(n: number): number { if (n <= 1) return 1; else return n * factorial(n - 1); } calls factorial inside itself with n-1, which is recursion.Step 2: Check base case correctness
function factorial(n: number): number { if (n <= 1) return 1; else return n * factorial(n - 1); } returns 1 when n <= 1, preventing infinite calls.Final Answer:
function factorial(n: number): number { if (n <= 1) return 1; else return n * factorial(n - 1); } -> Option DQuick Check:
Recursive call with base case = function factorial(n: number): number { if (n <= 1) return 1; else return n * factorial(n - 1); } [OK]
- Missing base case causing infinite recursion
- Using loops instead of recursive calls
- Incorrect base case values
function printNumbers(n: number): void {
if (n === 0) return;
printNumbers(n - 1);
console.log(n);
}
printNumbers(3);Solution
Step 1: Trace recursive calls
printNumbers(3) calls printNumbers(2), which calls printNumbers(1), then printNumbers(0) returns immediately.Step 2: Understand console.log order
After reaching base case, console.log prints n while unwinding: prints 1, then 2, then 3.Final Answer:
1 2 3 -> Option BQuick Check:
Recursion unwinds printing ascending numbers [OK]
- Assuming print before recursive call prints descending
- Including 0 in output incorrectly
- Confusing order of prints
function sumToN(n: number): number {
return n + sumToN(n - 1);
}Solution
Step 1: Identify missing base case
The function calls itself without stopping condition, causing infinite recursion.Step 2: Add base case to stop recursion
Adding if (n <= 0) return 0; stops recursion and returns correct sum.Final Answer:
Add a base case to stop recursion when n <= 0 -> Option AQuick Check:
Base case prevents infinite recursion [OK]
- Forgetting base case causes stack overflow
- Changing return to console.log does not fix recursion
- Removing parameter breaks logic
[1, [2, [3, 4], 5], 6] into a single array [1, 2, 3, 4, 5, 6]. Why is recursion a better choice than loops here?Solution
Step 1: Understand nested structure
The array has unknown depth of nested arrays, which loops alone cannot easily handle.Step 2: Recursion handles unknown depth
Recursion calls itself on nested arrays, flattening all levels naturally without complex loops.Final Answer:
Because recursion naturally handles unknown levels of nesting by calling itself -> Option CQuick Check:
Recursion = natural for unknown nested depth [OK]
- Thinking loops can flatten any nested array easily
- Believing recursion always uses less memory
- Assuming loops cannot access array elements
Ready to prove it?
Pass the test and this pattern moves unknown
