Login

Sign Up

Recursion
Tushar Varshney

Posted on Jan 15, 2025 | Coding

Recursion

Hey Coders! today, we are going to dive deeper into the concept of recursion. We'll explore how recursion works, its fundamental principles, and see some practical examples in action.


List of content:

  • Definition.
  • Need of Recursion.
  • Types of Recursion.
  • Examples with Outputs.
  • Advantages and disadvantages over iteration.

Let's start.....


Definition:

Recursion is a programming technique where a function calls itself in order to solve a problem. The idea is to break down a complex problem into smaller, more manageable sub-problems, solving each one recursively until reaching a base case that can be solved directly.

where,

  • Base case: This is the condition that stops the recursion. When the function reaches this point, it returns a direct result without making further recursive calls.
  • Recursive case: This is where the function calls itself with a smaller or simpler version of the original problem.

Consider an example of factorial number-

function factorial(n):
    if n == 0 or n == 1:           // Base Case
        return 1
        
    else:                          // Recursive Case
        return n * factorial(n - 1)


Need of Recursion:

  • Recursion can simplify the solution of complex problems by breaking them down into smaller, more manageable sub-problems.
  • Recursive functions can be more readable and easier to understand than their iterative counterparts.
  • In many cases, recursion can lead to more efficient use of memory through techniques like tail recursion.
  • Recursion is crucial for algorithms that involve backtracking, such as solving puzzles (e.g., Sudoku),etc.
  • Many fundamental algorithms, such as QuickSort, MergeSort, and binary search, rely on recursion.
  • Recursion is used in mathematical and theoretical computations, such as calculating factorials, generating Fibonacci sequences, and solving differential equations.

Types of Recursion:

  • Direct Recursion: This occurs when a function directly calls itself.

      function recursiveFunction(parameters):
      if base_condition:
          return base_value
      else:
          return recursiveFunction(modified_parameters)
    
    

    Example of Direct recursion:

    • Tail Recursion
    • Tree Recursion
    • Nested Recursion
  • Indirect Recursion: A function calls another function, which in turn calls the first function.

        function functionA(parameters):
      if base_conditionA:
          return base_valueA
      else:
          return functionB(modified_parameters)
    
      function functionB(parameters):
      if base_conditionB:
          return base_valueB
      else:
          return functionA(modified_parameters)
    
    

Some common Examples:

1. Sum of Natural Numbers:

In this problem we have to find the sum of N Natural numbers..

Approach 1 - Adding elements one by one..

F(n) = 0 + 1 + 2 + 3 +……..+ n

but we have another approach to solve this

Approach 2 - Recursively Adding..

f(n) = 0 ,n=0
f(n) = n + f(n-1) ,n>=1

Code in C:

#include<stdio.h>

int SumOfNatural(int n){
    if(n==0) return 0;        // base case
    
    return (n + SumOfNatural(n-1));    //  recursive case
}


void main(){
    int n = 4;
    printf("%d",SumOfNatural(n));
}

Code in Java:

class solution{
    public int SumOFNatural(int n){
        if(n==0) return 0;  // Base case
    
        return (n + SumOfNatural(n-1)); // recursive case
    }

    public static void main(String[] args){
        int n = 4;
        System.out.println(SumOfNatural(n));
    }
}

Code in C++:

#include<bits/stdc++.h>
using namespace std;

int SumOfNatural(int n){
    if(n==0) return 0;        // base case
    
    return (n + SumOfNatural(n-1));    //  recursive case
}


int main(){
    int n = 4;
    cout<<SumOfNatural(n);
    return 0;
}

Output:

Output: 10

2. Factorial Number:

The factorial of a number 𝑛(denoted as 𝑛!) is the product of all positive integers less than or equal to 𝑛.

Approach 1 - By Multiply one by one..

F(n) = 1* 2* 3* 4*....*n

but we have another approach to solve this

Approach 2 - Recursive approach..

F(n) = 1 ,n=0
F(n) = n*F(n-1) ,n>=1

Code in C:

#include<stdio.h>

int factorial(int n){
    if(n==0) return 1;  // Base case
    
    return (n*factorial(n-1));  // recursive case
} 


void main(){
    int n = 4;
    printf("%d",factorial(n));
}

Code in Java:

class solution{
    public int factorial(int n){
        if(n==0) return 1;  // Base case
    
        return (n*factorial(n-1)); // recursive case
    }

    public static void main(String[] args){
        int n = 4;
        System.out.println(factorial(n));
    }
}

Code in C++:

#include<bits/stdc++.h>
using namespace std;

int factorial(int n){
    if(n==0) return 1;  // Base case
    
    return (n*factorial(n-1));  // recursive case
} 


int main(){
    int n = 4;
    cout<<factorial(n);
    return 0;
}

Output:

Output: 24

3. Fibonacci series:

The Fibonacci series is a sequence of numbers where each number is the sum of the two preceding ones, usually starting with 0 and 1.

Approach 1 - Mathematically approach..

F(n) = 0+1+1+2+...nth

but we have another approach to solve this

Approach 2 - Recursive approach..

F(n) = 0 1 , n=0 , n=1
F(n) = F(n-1) + F(n-2) ,otherwise

Code in C:

#include<stdio.h>

int fib(int n){
    if (n == 0) return 0;                // Base Case
    
    if (n == 1 || n == 2) return 1;      // Base case

    // Recursion function
    return (fib(n - 1) + fib(n - 2));
}

void main(){
    int n = 5;
    printf("Fibonacci series of %d numbers is: ",n);
    
    for (int i = 0; i < n; i++) {
        printf("%d ", fib(i));
    }
}

Code in Java:

class solution{
    public int fib(int n){
        if(n==0) return 0;  // Base case
        if (n == 1 || n == 2) return 1;      // Base case
        
        return (fib(n - 1) + fib(n - 2)); // recursive case
    }

    public static void main(String[] args){
        int n = 5;
        System.out.println("Fibonacci series of "+ n + "is: ");
        for (int i = 0; i < n; i++) {
            System.out.println(fib(i));
        }
    }
}

Code in C++:

#include<bits/stdc++.h>
using namespace std;

int fib(int n){
    if (n == 0) return 0;                // Base Case
    
    if (n == 1 || n == 2) return 1;      // Base case

    // Recursion function
    return (fib(n - 1) + fib(n - 2));
}

int main(){
    int n = 5;
    cout<<"Fibonacci series of "<<n<<" numbers is: ";
    
    for (int i = 0; i < n; i++) {
        cout<<fib(i);
    }
    return 0;
}

Output:

Output: Fibonacci sereis of 5 is: 0 1 1 2 3


Advantages and disadvantages over iteration:

Aspect Recursion Iteration
Code Readability Often more readable and intuitive, especially for problems with a naturally recursive structure. Can be less readable for complex problems but more straightforward for simple loops.
Maintainability Recursive code can be easier to maintain and debug. Iterative code can become complex and harder to maintain for certain problems.
Memory Usage Can lead to higher memory usage due to call stack growth, potentially causing stack overflow. Generally more efficient in terms of memory usage, as it uses a fixed amount of memory.
Performance May have higher overhead due to multiple function calls. Can be optimized using tail recursion and memoization. Typically faster for simple loops, with lower overhead and better performance for non-recursive problems.
Problem Solving Ideal for problems that naturally fit a recursive approach (e.g., tree traversals, combinatorial problems). Better suited for problems that can be solved with repetitive loops.
Dynamic Programming Often used in dynamic programming and memoization to solve overlapping subproblems efficiently. Can also be used in dynamic programming but may require more complex state management.
Backtracking Essential for backtracking algorithms (e.g., Sudoku, N-Queens problem). More challenging to implement backtracking with iteration alone.
Base Case Requires careful definition of base cases to prevent infinite recursion. No need for base cases; straightforward loop conditions.
Debugging Easier to debug for naturally recursive problems but harder for complex recursion. Easier to debug for straightforward problems but can be challenging for complex loops.

For more topics click here.

Happy Coding!

6 Reactions

0 Bookmarks

Read next

Tushar Varshney

Tushar Varshney

Jan 6, 25

5 min read

|

Problem on Bubble Sort

Tushar Varshney

Tushar Varshney

Jan 8, 25

6 min read

|

Problem on Selection sort