Practice Recursion

Table of contents
  1. Simple Recursion Exercises
  2. Medium Recursion Exercises
  3. Advanced Recursion Exercises

Recursion Practice Problems

Let’s start with some simple recursion exercises to build a solid understanding, then move to medium-level problems, and finally tackle exercises that require memoization or optimization.

Simple Recursion Exercises

1. Sum of Natural Numbers

Write a recursive method sumToN(int n) that returns the sum of natural numbers from 1 to n.

Test Case:

sumToN(5);  // Output: 15 (1 + 2 + 3 + 4 + 5)
Answer
   public int sumToN(int n) {
      if (n == 0) {  // Base case
         return 0;
      }
      return n + sumToN(n - 1);  // Recursive case
   }

2. Factorial

Write a recursive method factorial(int n) that returns the factorial of n.

Test Case:

factorial(5);  // Output: 120 (5 * 4 * 3 * 2 * 1)
Answer
   public int factorial(int n) {
      if (n == 0) {  // Base case
         return 1;
      }
      return n * factorial(n - 1);  // Recursive case
   }

3. Power of a Number

Write a recursive method power(int base, int exp) that returns base raised to the power of exp.

Test Case:

power(2, 4);  // Output: 16 (2^4)
Answer
   public int power(int base, int exp) {
      if (exp == 0) {  // Base case
         return 1;
      }
      return base * power(base, exp - 1);  // Recursive case
   }

4. Print Numbers from N to 1

Write a recursive method printToOne(int n) that prints numbers from n to 1.

Test Case:

printToOne(5);  // Output: 5, 4, 3, 2, 1
Answer
   public void printToOne(int n) {
      if (n == 0) {  // Base case
         return;
      }
      System.out.println(n);
      printToOne(n - 1);  // Recursive case
   }

5. Reverse a String

Write a recursive method reverseString(String s) that returns the reverse of the string s.

Test Case:

reverseString("hello");  // Output: "olleh"

Medium Recursion Exercises

6. Fibonacci Sequence

Write a recursive method fibonacci(int n) that returns the nth Fibonacci number.

Test Case:

fibonacci(5);  // Output: 5 (Fibonacci sequence: 0, 1, 1, 2, 3, 5)

7. Count the Digits of a Number

Write a recursive method countDigits(int n) that returns the number of digits in n.

Test Case:

countDigits(12345);  // Output: 5
Answer
   public int countDigits(int n) {
      if (n == 0) {  // Base case
         return 0;
      }
      return 1 + countDigits(n / 10);  // Recursive case
   }

8. Sum of Digits

Write a recursive method sumOfDigits(int n) that returns the sum of the digits of n.

Test Case:

sumOfDigits(123);  // Output: 6 (1 + 2 + 3)

9. Greatest Common Divisor (GCD)

Write a recursive method gcd(int a, int b) that returns the greatest common divisor of a and b.

Test Case:

gcd(48, 18);  // Output: 6

10. Decimal to Binary Conversion

Write a recursive method decimalToBinary(int n) that returns the binary representation of n as a string.

Test Case:

decimalToBinary(10);  // Output: "1010"

Advanced Recursion Exercises (With Memoization)

11. Fibonacci with Memoization

Improve the Fibonacci sequence method using memoization to store already computed values.

Test Case:

int[] memo = new int[6];  // Initialize memo array
fibonacciMemo(5, memo);  // Output: 5
Answer
   public int fibonacciMemo(int n, int[] memo) {
      if (n == 0 || n == 1) {
         return n;  // Base case
      }
      if (memo[n] == 0) {  // Only compute if not already in memo
         memo[n] = fibonacciMemo(n - 1, memo) + fibonacciMemo(n - 2, memo);  // Recursive case
      }
      return memo[n];
   }

12. Climbing Stairs Problem

There are n stairs, and you can climb 1 or 2 stairs at a time. Write a method climbStairs(int n) to calculate the number of distinct ways to reach the top.

Test Case:

int[] memo = new int[6];
climbStairs(5, memo);  // Output: 8
Answer
   public int climbStairs(int n, int[] memo) {
      if (n == 0 || n == 1) {  // Base cases
         return 1;
      }
      if (memo[n] == 0) {  // Only compute if not already in memo
         memo[n] = climbStairs(n - 1, memo) + climbStairs(n - 2, memo);  // Recursive case
      }
      return memo[n];
   }

13. Minimum Path Sum (2D Grid)

Write a recursive method minPathSum(int[][] grid) that calculates the minimum path sum from the top-left to the bottom-right corner of a grid, using memoization.

Test Case:

int[][] grid = { {1, 3, 1}, {1, 5, 1}, {4, 2, 1} };
int[][] memo = new int[3][3];
minPathSum(grid, 0, 0, memo);  // Output: 7
Answer
   public int minPathSum(int[][] grid, int i, int j, int[][] memo) {
      if (i == grid.length - 1 && j == grid[0].length - 1) {  // Base case: reached bottom-right
         return grid[i][j];
      }
      if (i >= grid.length || j >= grid[0].length) {  // Out of bounds
         return Integer.MAX_VALUE;
      }
      if (memo[i][j] == 0) {
         int down = minPathSum(grid, i + 1, j, memo);
         int right = minPathSum(grid, i, j + 1, memo);
         memo[i][j] = grid[i][j] + Math.min(down, right);  // Recursive case
      }
      return memo[i][j];
   }

14. Longest Increasing Subsequence (LIS) with Memoization

Write a recursive method lis(int[] arr) to find the length of the longest increasing subsequence in an array using memoization.

Test Case:

int[] arr = {10, 22, 9, 33, 21, 50, 41, 60, 80};
int[] memo = new int[arr.length + 1];
lis(arr, arr.length, memo);  // Output: 6
Answer
   public int lis(int[] arr, int n, int[] memo) {
      if(n == 1) {  // Base case
         return 1;
      }
      if (memo[n] != 0) {
         return memo[n];
      }
      int maxEndingHere = 1;  // Initialize with length 1
      for (int i = 1; i < n; i++) {
         int res = lis(arr, i, memo);
         if (arr[i - 1] < arr[n - 1]) {
               maxEndingHere = Math.max(maxEndingHere, res + 1);
         }
      }
      memo[n] = maxEndingHere;
      return memo[n];
   }

15. Coin Change Problem

Write a recursive method coinChange(int[] coins, int amount) that calculates the minimum number of coins needed to make up a given amount, using memoization.

Test Case:

int[] coins = {1, 2, 5};
int[] memo = new int[12];
coinChange(coins, 11, memo);  // Output: 3 (11 = 5 + 5 + 1)
Answer
   public int coinChange(int[] coins, int amount, int[] memo) {
      if (amount == 0) {  // Base case
         return 0;
      }
      if (memo[amount] != 0) {
         return memo[amount];
      }
      int minCoins = Integer.MAX_VALUE;
      for (int coin : coins) {
         if (amount - coin >= 0) {
               int result = coinChange(coins, amount - coin, memo);
               if (result >= 0 && result < minCoins) {
                  minCoins = result + 1;
               }
         }
      }
      memo[amount] = (minCoins == Integer.MAX_VALUE) ? -1 : minCoins;
      return memo[amount];
   }

These problems should help you gradually strengthen your understanding of recursion, from simple base case-recursive case exercises to more complex memoization-based optimization problems.

Back to Top