Recursion is a technique where a function calls itself to solve a problem by breaking it into smaller, similar subproblems until a base condition is met.
- A function invokes itself during execution.
- Works by dividing a problem into smaller subproblems.
- Requires a base case to stop infinite calls.
- Commonly used in problems like factorial, Fibonacci, and tree traversal.
function sum(n) {
if (n === 0) {
return 0; // base case
}
return n + sum(n - 1); // recursive call
}
console.log(sum(5));
Syntax:
function recursiveFunction(parameters) {
// Base case: stopping condition
if (baseCase) {
return baseCaseValue;
}
// Recursive case: function calls itself
return recursiveFunction(modifiedParameters);
}
Core Elements of Recursion
The core elements of recursion define how a function repeatedly calls itself while progressing toward a stopping condition.
1. Base Case
The base case defines the condition that stops the recursive calls and prevents infinite recursion.
- Condition that stops further recursive calls
- Prevents infinite recursion and stack overflow
- Example: In factorial, when n is 0 or 1
2. Recursive Case
The recursive case is the part of the function where it calls itself with a modified input to move closer to the base case.
- Part where the function calls itself
- Input is reduced or modified to approach the base case
- Example: n * factorial(n - 1)
Example : Factorial of a Number
function factorial(n) {
// Base case: if n is 0 or 1, return 1
if (n === 0 || n === 1) {
return 1;
}
// Recursive case: n! = n * (n-1)!
return n * factorial(n - 1);
}
console.log(factorial(5)); // Output: 120
Benefits of Using Recursion
Recursion is particularly useful for solving problems that can be divided into smaller, identical problems. Some common use cases include:
- Tree and Graph Traversals: Recursion is ideal for traversing hierarchical data structures like trees and graphs.
- Divide and Conquer Algorithms: Many algorithms, such as Merge Sort and Quick Sort, use recursion to break down problems into smaller subproblems.
- Backtracking: Recursion is often used in backtracking algorithms to explore all possible solutions.
[Example 1]: Fibonacci Sequence
The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones (e.g., 0, 1, 1, 2, 3, 5, 8, ...).
function fibonacci(n) {
// Base case: return n if n is 0 or 1
if (n === 0 || n === 1) {
return n;
}
// Recursive case: sum of the two preceding numbers
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(6)); // Output: 8
Application of Recursion
1. Mathematical Computations
- Factorial calculation
- Fibonacci sequence
- Greatest Common Divisor (GCD)
2. Data Structures
- Tree traversal (Preorder, Inorder, Postorder)
- Graph traversal (Depth-First Search)
- Linked list operations (Reversal, Searching)
3. Sorting Algorithms
- Merge Sort
- Quick Sort
4. Backtracking
- N-Queens problem
- Sudoku solver
- Maze solving
5.Dynamic Programming
- Fibonacci sequence optimization
- Longest Common Subsequence (LCS)
- Knapsack problem
6.File System Operations
- Directory traversal
- Searching for files in nested folders
Tail Recursion
Tail Recursion is a type of recursion where the recursive call is the final operation in a function, allowing optimizations that reduce call stack usage and improve memory efficiency.
- Recursive call is the last statement.
- No computation after the recursive call.
- Can be optimized to avoid stack growth.
- More memory-efficient than normal recursion.
Characteristics of Tail Recursion
- Last Operation: The recursive call must be the last operation in the function.
- No Pending Work: The function should not perform any computation after the recursive call.
- Optimization: Tail-recursive functions can be optimized into a loop by the compiler or interpreter, avoiding stack overflow.
When to Use Tail Recursion
- Use tail recursion when you need to solve a problem recursively and want to avoid stack overflow.
- Tail recursion is particularly useful for problems that involve large inputs or deep recursion.
Example: Factorial with Tail Recursion
function factorial(n, accumulator = 1) {
// Base case:
if (n === 0 || n === 1) {
return accumulator;
}
// Tail-recursive call:
return factorial(n - 1, n * accumulator);
}
console.log(factorial(5));
Also Check:
- Easy Problems on Recursion in JS
- Print 1 to n without loop
- Print n to 1 without loop
- Mean of Array using Recursion
- Sum of natural numbers using recursion
- Decimal to binary number using recursion
- Sum of array elements using recursion
- Medium Problems on Recursion in JS
- Binary to Gray code using recursion
- Delete a linked list using recursion
- Product of 2 Numbers using Recursion
- Programs for Printing Pyramid Patterns using Recursion
- Length of longest palindromic sub-string : Recursion
- Hard Problems on Recursion in JS
- Check if a string is a scrambled form of another string
- Word Break Problem | DP-32
- Print all palindromic partitions of a string
- N Queen Problem | Backtracking-3
- Algorithm to Solve Sudoku | Sudoku Solver