ArrayProblem 22 of 36

Find factorial of a large number

Brute Force
Time: O(n²)
Space: O(n)
Optimal
Time: O(n²)
Space: O(n)

Problem Statement

Given a positive integer n, find the factorial of n. For large numbers, the result won't fit in standard data types, so store it in an array or string.

Example:

  • Input: n = 100
  • Output: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

Approach 1: Using Array Multiplication (Brute Force)

Intuition

Simulate multiplication the way we do it by hand - multiply each digit and handle carry.

Algorithm

  1. Store result in an array where each element is a single digit
  2. For each number from 2 to n:
    • Multiply each digit by the current number
    • Handle carry appropriately
  3. Result array contains digits in reverse order
java
import java.util.*;

public class Solution {
    public String factorialBruteForce(int n) {
        if (n == 0 || n == 1) return "1";
        
        List<Integer> result = new ArrayList<>();
        result.add(1);
        
        for (int x = 2; x <= n; x++) {
            int carry = 0;
            
            // Multiply each digit by x
            for (int i = 0; i < result.size(); i++) {
                int prod = result.get(i) * x + carry;
                result.set(i, prod % 10);
                carry = prod / 10;
            }
            
            // Handle remaining carry
            while (carry > 0) {
                result.add(carry % 10);
                carry /= 10;
            }
        }
        
        // Convert to string (reverse order)
        StringBuilder ans = new StringBuilder();
        for (int i = result.size() - 1; i >= 0; i--) {
            ans.append(result.get(i));
        }
        
        return ans.toString();
    }
}

Complexity Analysis

  • Time Complexity: O(n² × d) where d is the number of digits in result
  • Space Complexity: O(d) - Storing the result digits

Approach 2: Optimized Array Multiplication

Intuition

Instead of storing single digits, store larger chunks (like 4 digits per element) to reduce operations.

Algorithm

  1. Use base 10000 instead of base 10
  2. Each array element holds up to 4 digits
  3. Perform same multiplication with optimized chunk size
java
import java.util.*;
import java.math.BigInteger;

public class Solution {
    public String factorialOptimized(int n) {
        if (n == 0 || n == 1) return "1";
        
        final int BASE = 10000;  // Store 4 digits per element
        List<Long> result = new ArrayList<>();
        result.add(1L);
        
        for (int x = 2; x <= n; x++) {
            long carry = 0;
            
            for (int i = 0; i < result.size(); i++) {
                long prod = result.get(i) * x + carry;
                result.set(i, prod % BASE);
                carry = prod / BASE;
            }
            
            while (carry > 0) {
                result.add(carry % BASE);
                carry /= BASE;
            }
        }
        
        // Convert to string
        StringBuilder ans = new StringBuilder();
        ans.append(result.get(result.size() - 1));  // First chunk
        
        for (int i = result.size() - 2; i >= 0; i--) {
            String chunk = String.format("%04d", result.get(i));
            ans.append(chunk);
        }
        
        return ans.toString();
    }
    
    // Using BigInteger
    public String factorialBigInteger(int n) {
        BigInteger result = BigInteger.ONE;
        for (int i = 2; i <= n; i++) {
            result = result.multiply(BigInteger.valueOf(i));
        }
        return result.toString();
    }
}

Complexity Analysis

  • Time Complexity: O(n² × d/k) where k is digits per chunk (4 in this case)
  • Space Complexity: O(d/k) - Reduced array size

Approach 3: Using Prime Factorization

Intuition

Count the power of each prime in n! and multiply them together. This is more efficient for very large n.


Visual Example

For n = 5 (5! = 120):

Initial: result = [1] x = 2: 1 × 2 = 2, carry = 0 result = [2] x = 3: 2 × 3 = 6, carry = 0 result = [6] x = 4: 6 × 4 = 24 24 % 10 = 4, carry = 2 result = [4] Add carry: result = [4, 2] x = 5: 4 × 5 + 0 = 20, 20 % 10 = 0, carry = 2 2 × 5 + 2 = 12, 12 % 10 = 2, carry = 1 result = [0, 2] Add carry: result = [0, 2, 1] Final (reversed): "120"

Properties of Factorial

  1. Number of trailing zeros in n! = count of factor 5 in n!

    • Formula: ⌊n/5⌋ + ⌊n/25⌋ + ⌊n/125⌋ + ...
  2. Number of digits in n!log₁₀(n!) + 1

    • Using Stirling's approximation: n! ≈ √(2πn) × (n/e)^n

Key Takeaways

  1. Array-based multiplication is essential when result exceeds standard data types
  2. Using larger base (like 10000) reduces number of operations
  3. Handle carry propagation carefully in multiplication
  4. For languages with big integers (Python, Java BigInteger), use built-in support
  5. Prime factorization approach is theoretically more efficient for very large n
  6. Trailing zeros problem is a common related question