Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/main/java/com/thealgorithms/divideandconquer/Factorial.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.thealgorithms.divideandconquer;

/**
* Computes the factorial of a non-negative integer using an iterative
* approach to avoid recursion overhead and stack overflow risks.
*
* <p>This implementation improves upon the original recursive version by
* eliminating deep recursion, reducing space complexity from O(n) to O(1),
* and improving runtime efficiency on the JVM.
*
* <p>Time Complexity: O(n)
* <br>Space Complexity: O(1)
*/
public final class Factorial {

private Factorial() {
// Utility class
}

/**
* Returns the factorial of the given non-negative number.
*
* @param n the number to compute factorial for
* @return factorial of n (n!)
* @throws IllegalArgumentException if n is negative
*/
public static long factorial(long n) {
if (n < 0) {
throw new IllegalArgumentException("Negative input not allowed");
}

long result = 1;
for (long i = 2; i <= n; i++) {
result *= i;
}

return result;
}
}
23 changes: 0 additions & 23 deletions src/main/java/com/thealgorithms/maths/Factorial.java

This file was deleted.

18 changes: 0 additions & 18 deletions src/main/java/com/thealgorithms/maths/FactorialRecursion.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.thealgorithms.divideandconquer;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

public class FactorialTest {
// --------------------------------------------------------
// SECTION 1: Basic Correctness Tests
// --------------------------------------------------------

@Test
void testFactorialOfFive() {
assertEquals(120, Factorial.factorial(5));
}

@Test
void testFactorialOfZero() {
assertEquals(1, Factorial.factorial(0));
}

@Test
void testNegativeInputThrowsException() {
assertThrows(IllegalArgumentException.class, () -> { Factorial.factorial(-5); });
}

// --------------------------------------------------------
// SECTION 2: Analysis-Oriented Test (Performance Awareness)
// --------------------------------------------------------

@Test
void testLargeInputPerformance() {
long start = System.currentTimeMillis();
long result = Factorial.factorial(15);
long end = System.currentTimeMillis();

assertEquals(1307674368000L, result);
assertTrue((end - start) < 50, "Factorial(15) took too long to compute");
}

// --------------------------------------------------------
// SECTION 3: Algorithmic Improvement Demonstration
// --------------------------------------------------------

/**
* Local copy of the original recursive implementation
* used only for comparing performance inside the test.
*/
private long recursiveFactorial(long n) {
if (n < 0) {
throw new IllegalArgumentException("Negative input not allowed");
}
if (n == 0 || n == 1) {
return 1;
}
return n * recursiveFactorial(n - 1);
}

@Test
void testIterativeFasterThanRecursive() {
long n = 18;

long startRec = System.nanoTime();
long recResult = recursiveFactorial(n);
long endRec = System.nanoTime();

long startIter = System.nanoTime();
long iterResult = Factorial.factorial(n);
long endIter = System.nanoTime();

assertEquals(recResult, iterResult);
assertTrue(endIter - startIter < endRec - startRec, "Iterative version should outperform recursive version");
}

@Test
void testIterativeHandlesLargerInputsSafely() {
assertDoesNotThrow(() -> Factorial.factorial(20));
}
}

This file was deleted.

24 changes: 0 additions & 24 deletions src/test/java/com/thealgorithms/maths/FactorialTest.java

This file was deleted.