diff --git a/src/main/java/com/thealgorithms/maths/CatalanNumbers.java b/src/main/java/com/thealgorithms/maths/CatalanNumbers.java index 387756bdfa0c..2f304d1c2b3c 100644 --- a/src/main/java/com/thealgorithms/maths/CatalanNumbers.java +++ b/src/main/java/com/thealgorithms/maths/CatalanNumbers.java @@ -1,38 +1,43 @@ package com.thealgorithms.maths; +import java.math.BigInteger; + /** * Calculate Catalan Numbers */ public final class CatalanNumbers { + private static final int MAX_SUPPORTED_INDEX = 35; + private CatalanNumbers() { } /** - * Calculate the nth Catalan number using a recursive formula. + * Calculate the nth Catalan number using the factorial formula. * * @param n the index of the Catalan number to compute * @return the nth Catalan number + * @throws IllegalArgumentException if n is negative or exceeds the maximum supported index for long */ public static long catalan(final int n) { if (n < 0) { throw new IllegalArgumentException("Index must be non-negative"); } - return factorial(2 * n) / (factorial(n + 1) * factorial(n)); + if (n > MAX_SUPPORTED_INDEX) { + throw new IllegalArgumentException("Index exceeds maximum supported value for long"); + } + return factorial(2 * n).divide(factorial(n + 1).multiply(factorial(n))).longValueExact(); } /** - * Calculate the factorial of a number. + * Calculate the factorial of a number using BigInteger to prevent integer overflow. * * @param n the number to compute the factorial for - * @return the factorial of n + * @return the factorial of n as BigInteger */ - private static long factorial(final int n) { - if (n == 0 || n == 1) { - return 1; - } - long result = 1; + private static BigInteger factorial(final int n) { + BigInteger result = BigInteger.ONE; for (int i = 2; i <= n; i++) { - result *= i; + result = result.multiply(BigInteger.valueOf(i)); } return result; } diff --git a/src/test/java/com/thealgorithms/maths/CatalanNumbersTest.java b/src/test/java/com/thealgorithms/maths/CatalanNumbersTest.java index 2248ffd93732..cf8b1ddabc98 100644 --- a/src/test/java/com/thealgorithms/maths/CatalanNumbersTest.java +++ b/src/test/java/com/thealgorithms/maths/CatalanNumbersTest.java @@ -19,7 +19,8 @@ class CatalanNumbersTest { * [input number, expected Catalan number for that input] */ static Stream catalanNumbersProvider() { - return Stream.of(new Object[] {0, 1}, new Object[] {1, 1}, new Object[] {2, 2}, new Object[] {3, 5}, new Object[] {4, 14}, new Object[] {5, 42}, new Object[] {6, 132}, new Object[] {7, 429}, new Object[] {8, 1430}, new Object[] {9, 4862}, new Object[] {10, 16796}); + return Stream.of(new Object[] {0, 1L}, new Object[] {1, 1L}, new Object[] {2, 2L}, new Object[] {3, 5L}, new Object[] {4, 14L}, new Object[] {5, 42L}, new Object[] {6, 132L}, new Object[] {7, 429L}, new Object[] {8, 1430L}, new Object[] {9, 4862L}, new Object[] {10, 16796L}, + new Object[] {11, 58786L}, new Object[] {15, 9694845L}, new Object[] {35, 3116285494907301262L}); } /** @@ -28,7 +29,7 @@ static Stream catalanNumbersProvider() { */ @ParameterizedTest @MethodSource("catalanNumbersProvider") - void testCatalanNumbers(int input, int expected) { + void testCatalanNumbers(int input, long expected) { assertEquals(expected, CatalanNumbers.catalan(input), () -> String.format("Catalan number for input %d should be %d", input, expected)); } @@ -39,5 +40,6 @@ void testCatalanNumbers(int input, int expected) { void testIllegalInput() { assertThrows(IllegalArgumentException.class, () -> CatalanNumbers.catalan(-1)); assertThrows(IllegalArgumentException.class, () -> CatalanNumbers.catalan(-5)); + assertThrows(IllegalArgumentException.class, () -> CatalanNumbers.catalan(36)); } }