Skip to content

Factorial

The factorial of a non-negative integer \(n\), denoted by \(n!\), is the product of all positive integers less than or equal to \(n\). \(n! = n \times (n-1) \times (n-2) \times ... \times 1\)

1. Iterative Implementation

Efficient and avoids recursion overhead.

public static long factorialIterative(int n) {
    long res = 1;
    for (int i = 2; i <= n; i++) {
        res *= i;
    }
    return res;
}

2. Recursive Implementation

A classic example of recursion. \(n! = n \times (n-1)!\) base case: \(0! = 1\).

public static long factorialRecursive(int n) {
    if (n == 0) return 1;
    return n * factorialRecursive(n - 1);
}

3. BigInteger for Large Factorials

long in Java can only store up to \(20!\). For larger numbers, use java.math.BigInteger.

import java.math.BigInteger;

public static BigInteger factorialLarge(int n) {
    BigInteger res = BigInteger.ONE;
    for (int i = 2; i <= n; i++) {
        res = res.multiply(BigInteger.valueOf(i));
    }
    return res;
}

Trailing Zeros in Factorial

The number of trailing zeros in \(n!\) is determined by the count of factors of 5 in the prime factorization of \(x!\). Formula: \(\lfloor n/5 \rfloor + \lfloor n/25 \rfloor + \lfloor n/125 \rfloor + ...\)

public static int countTrailingZeros(int n) {
    int count = 0;
    while (n >= 5) {
        n /= 5;
        count += n;
    }
    return count;
}

Complexity

Metric Complexity Description
Time \(O(n)\) One loop or \(n\) recursive calls.
Space \(O(1)\) Iterative uses constant space. Recursive uses \(O(n)\) stack space.

Applications

  • Permutations: \(P(n, r) = \frac{n!}{(n-r)!}\)
  • Combinations: \(C(n, r) = \frac{n!}{r!(n-r)!}\)
  • Probability theory.

Key Takeaways

  • Overflow: \(n!\) grows extremely fast. \(21!\) overflows a 64-bit long.
  • Base Case: Always define \(0! = 1\) to ensure correct recursive results.
  • Zeros: Counting trailing zeros is a common competitive programming trick using power of 5.