Skip to content

Commit 441359b

Browse files
refactor: remove duplicate factorial implementations and add improved iterative factorial with full test suite
1 parent a9ba87c commit 441359b

File tree

6 files changed

+111
-92
lines changed

6 files changed

+111
-92
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.thealgorithms.divideandconquer;
2+
/**
3+
* Computes the factorial of a non-negative integer using an iterative
4+
* approach to avoid recursion overhead and stack overflow risks.
5+
*
6+
* <p>This implementation improves upon the original recursive version by
7+
* eliminating deep recursion, reducing space complexity from O(n) to O(1),
8+
* and improving runtime efficiency on the JVM.
9+
*
10+
* <p>Time Complexity: O(n)
11+
* <br>Space Complexity: O(1)
12+
*/
13+
public class Factorial {
14+
/**
15+
* Returns the factorial of the given non-negative number.
16+
*
17+
* @param n the number to compute factorial for
18+
* @return factorial of n (n!)
19+
* @throws IllegalArgumentException if n is negative
20+
*/
21+
public static long factorial(long n) {
22+
if (n < 0) {
23+
throw new IllegalArgumentException("Negative input not allowed");
24+
}
25+
26+
long result = 1;
27+
for (long i = 2; i <= n; i++) {
28+
result *= i;
29+
}
30+
31+
return result;
32+
}
33+
}

src/main/java/com/thealgorithms/maths/Factorial.java

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/main/java/com/thealgorithms/maths/FactorialRecursion.java

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.thealgorithms.divideandconquer;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
import org.junit.jupiter.api.Test;
5+
6+
7+
public class FactorialTest {
8+
// --------------------------------------------------------
9+
// SECTION 1: Basic Correctness Tests
10+
// --------------------------------------------------------
11+
12+
@Test
13+
void testFactorialOfFive() {
14+
assertEquals(120, Factorial.factorial(5));
15+
}
16+
17+
@Test
18+
void testFactorialOfZero() {
19+
assertEquals(1, Factorial.factorial(0));
20+
}
21+
22+
@Test
23+
void testNegativeInputThrowsException() {
24+
assertThrows(IllegalArgumentException.class, () -> {
25+
Factorial.factorial(-5);
26+
});
27+
}
28+
29+
// --------------------------------------------------------
30+
// SECTION 2: Analysis-Oriented Test (Performance Awareness)
31+
// --------------------------------------------------------
32+
33+
@Test
34+
void testLargeInputPerformance() {
35+
long start = System.currentTimeMillis();
36+
long result = Factorial.factorial(15);
37+
long end = System.currentTimeMillis();
38+
39+
assertEquals(1307674368000L, result);
40+
assertTrue((end - start) < 50, "Factorial(15) took too long to compute");
41+
}
42+
43+
// --------------------------------------------------------
44+
// SECTION 3: Algorithmic Improvement Demonstration
45+
// --------------------------------------------------------
46+
47+
/**
48+
* Local copy of the original recursive implementation
49+
* used only for comparing performance inside the test.
50+
*/
51+
private long recursiveFactorial(long n) {
52+
if (n < 0) throw new IllegalArgumentException("Negative input not allowed");
53+
if (n == 0 || n == 1) return 1;
54+
return n * recursiveFactorial(n - 1);
55+
}
56+
57+
@Test
58+
void testIterativeFasterThanRecursive() {
59+
long n = 18;
60+
61+
long startRec = System.nanoTime();
62+
long recResult = recursiveFactorial(n);
63+
long endRec = System.nanoTime();
64+
65+
long startIter = System.nanoTime();
66+
long iterResult = Factorial.factorial(n);
67+
long endIter = System.nanoTime();
68+
69+
assertEquals(recResult, iterResult);
70+
assertTrue(endIter - startIter < endRec - startRec,
71+
"Iterative version should outperform recursive version");
72+
}
73+
74+
@Test
75+
void testIterativeHandlesLargerInputsSafely() {
76+
assertDoesNotThrow(() -> Factorial.factorial(20));
77+
}
78+
}

src/test/java/com/thealgorithms/maths/FactorialRecursionTest.java

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/test/java/com/thealgorithms/maths/FactorialTest.java

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)