Back to Beginner: I/O, Arithmetic, Loops
Q6Question 6 of 30

Write a Recursive Function to Calculate Factorial of N

Key Concepts
  • Factorial of N (N!) is the product of all positive integers from 1 to N, defined recursively as fact(0) = 1 and fact(n) = n * fact(n-1).
  • The base case fact(0) = 1 stops the recursion; without it the calls never terminate and you get a StackOverflowError.
  • Factorials grow explosively: 13! overflows int and 21! overflows long, so banking code uses BigInteger.
  • Each recursive call adds a stack frame, so for very large N an iterative loop avoids StackOverflowError.
  • Negative input is undefined for factorial and must be rejected with IllegalArgumentException.
  • The recursive form mirrors the mathematical definition, making it easy to verify and explain in an interview.

Definition

Factorial of N is N times factorial of N minus one, and factorial of zero is one: the base case stops the recursion.
  • Factorial (N!) – the product of all positive integers from 1 up to N, growing extremely fast.
  • Base case – fact(0) = 1 returns the known answer directly and stops the recursion.
  • Recursive case – fact(n) = n * fact(n-1) reduces the problem by one on every call until it reaches zero.
  • Overflow danger – 13! exceeds int range and 21! exceeds long range, so financial code uses BigInteger.
  • Stack depth – each call adds a frame; for very large N an iterative version avoids StackOverflowError.

Suppose National Bank of India is arranging N different cheques in a row and wants to know how many different orders are possible. For the first slot there are N choices, for the next slot N minus one choices, and so on down to one. The total number of arrangements is N!. Rajesh asks Pankaj: the arrangements of N cheques equal N times the arrangements of the remaining N minus one cheques, and the arrangements of zero cheques is just one, the empty arrangement.

Understanding the Concepts

What is factorial?

The factorial of a non-negative integer N, written N!, is the product of all positive integers from 1 up to N. By definition, 0! equals 1 because the product of no numbers is the multiplicative identity.

  • 0! = 1
  • 1! = 1
  • 5! = 5 * 4 * 3 * 2 * 1 = 120
  • 10! = 3628800

How does the recursive definition work?

The mathematical definition is already recursive: fact(0) = 1 is the base case and fact(n) = n * fact(n-1) is the recursive case. Each call reduces N by one, so we are guaranteed to reach zero and stop.

JAVA
package com.bank.service;

import java.math.BigInteger;

public class FactorialCalculator {

    public static BigInteger factorial(int n) {
        if (n < 0) {
            throw new IllegalArgumentException("Factorial not defined for negative: " + n);
        }
        if (n == 0) {
            return BigInteger.ONE; // base case
        }
        return BigInteger.valueOf(n).multiply(factorial(n - 1)); // recursive case
    }

    public static void main(String[] args) {
        // How many ways can Rajesh arrange 5 cheques?
        System.out.println("5! = " + factorial(5));
        System.out.println("0! = " + factorial(0));
        System.out.println("20! = " + factorial(20));
    }
}
TEXT
5! = 120
0! = 1
20! = 2432902008176640000

Why does overflow matter in banking?

Factorials explode: 13! already exceeds the maximum value of a 32-bit int (2,147,483,647), and 21! exceeds a 64-bit long. In a financial system, using the wrong type silently produces a garbage negative number, which is dangerous.

JAVA
// Wrong: int overflows silently
int result = 1;
for (int i = 1; i <= 13; i++) result *= i;
System.out.println(result); // 1932053504 (WRONG, should be 6227020800)

// Correct: BigInteger never overflows
System.out.println(factorial(13)); // 6227020800

How is recursive different from iterative?

| Feature | Recursive | Iterative |
|---|---|---|
| Mirrors math definition | Yes, directly | No, uses a loop |
| Stack usage | O(n) frames | O(1) |
| Risk of StackOverflowError | Yes, for large N | No |
| Readability | Very clear | Slightly more code |
| Performance | Overhead per call | Slightly faster |

JAVA
// Iterative version: same result, no stack risk
public static BigInteger factorialIterative(int n) {
    if (n < 0) throw new IllegalArgumentException("Negative input");
    BigInteger result = BigInteger.ONE;
    for (int i = 2; i <= n; i++) {
        result = result.multiply(BigInteger.valueOf(i));
    }
    return result;
}

What happens with negative input?

Factorial is undefined for negative numbers. The method must validate and reject.

JAVA
try {
    factorial(-1);
} catch (IllegalArgumentException e) {
    System.out.println(e.getMessage()); // Factorial not defined for negative: -1
}

What are edge cases?

  • factorial(0) returns 1, the base case.
  • factorial(1) returns 1, since 1 * fact(0) = 1 * 1 = 1.
  • Very large N (e.g., 10000) works with BigInteger but would overflow the stack in the recursive version. Use the iterative version for large N.

What are common mistakes?

JAVA
// Wrong: missing base case causes infinite recursion
public static BigInteger factorialBroken(int n) {
    return BigInteger.valueOf(n).multiply(factorialBroken(n - 1));
    // Never stops! StackOverflowError
}

// Wrong: using int or long for the result
long result = 1;
for (int i = 1; i <= 25; i++) result *= i; // overflows past 20!

// Correct: BigInteger with proper base case
public static BigInteger factorialCorrect(int n) {
    if (n == 0) return BigInteger.ONE;
    return BigInteger.valueOf(n).multiply(factorialCorrect(n - 1));
}

What should a senior engineer know?

A senior engineer chooses between recursive and iterative based on the expected range of N. For teaching, interviews, and small N the recursive version is preferred because it reads like the mathematical definition. For production with potentially large N, the iterative version avoids the StackOverflowError risk.

Tail-call optimization would make recursion as efficient as iteration, but the JVM does not guarantee tail-call optimization, so in Java you cannot rely on it. Kotlin and Scala offer tailrec annotations for this.

Caching computed factorials is another senior optimization. If the same factorials are requested repeatedly, store them in a lookup table and return cached values.

What are common interview follow-up questions?

  • How would you compute the number of trailing zeros in N!?
  • Can you write factorial using Java Streams?
  • What is the time complexity of computing N! with BigInteger?

Visual Overview

DIAGRAM
  factorial(5)
       │
       ▼
  5 * factorial(4)
            │
            ▼
       4 * factorial(3)
                 │
                 ▼
            3 * factorial(2)
                      │
                      ▼
                 2 * factorial(1)
                           │
                           ▼
                      1 * factorial(0)
                                │
                                ▼
                           return 1  ← base case
                      return 1 * 1 = 1
                 return 2 * 1 = 2
            return 3 * 2 = 6
       return 4 * 6 = 24
  return 5 * 24 = 120

Key Takeaway

Factorial of N is the product of all positive integers from one up to N, and it has a naturally recursive definition. The base case is that the factorial of zero is one, and the recursive case is that the factorial of N equals N multiplied by the factorial of N minus one. In code the base case stops the recursion by returning one directly, and the recursive case reduces the problem by one on every call until it reaches zero.

The most important thing in real banking code is the choice of data type. Factorials grow explosively: thirteen factorial already overflows a thirty-two bit integer and twenty-one factorial overflows a sixty-four bit long. In a financial system an overflow silently produces a wrong, often negative, number, and that could corrupt a calculation without anyone noticing. So in a risk-scenario engine at National Bank of India, factorials are computed with BigInteger, which grows to any size and never overflows, and the input is validated to reject negative numbers because a negative factorial is undefined.

The senior-level nuance is that recursion costs a stack frame per call, so for a very large N the iterative loop is safer and avoids a StackOverflowError. The recursive form is elegant and correct for moderate inputs, but in production the form is chosen based on the expected range of N and whether the JVM stack can accommodate the depth.

Remember one sentence: factorial is N times factorial of N minus one with a base case of one at zero, and in banking always use BigInteger because int and long overflow silently.

---

Share
Use ← → arrow keys to navigate