diff --git a/src/main/java/com/thealgorithms/searches/ExponentialSearch.java b/src/main/java/com/thealgorithms/searches/ExponentialSearch.java index 9187dcbc2f4b..e666b9148aaa 100644 --- a/src/main/java/com/thealgorithms/searches/ExponentialSearch.java +++ b/src/main/java/com/thealgorithms/searches/ExponentialSearch.java @@ -46,6 +46,9 @@ public > int find(T[] array, T key) { range = range * 2; } - return Arrays.binarySearch(array, range / 2, Math.min(range, array.length), key); + // The candidate block is the inclusive index range [range / 2, range], so the + // exclusive upper bound handed to binarySearch has to be range + 1. + final int index = Arrays.binarySearch(array, range / 2, Math.min(range + 1, array.length), key); + return index >= 0 ? index : -1; } } diff --git a/src/test/java/com/thealgorithms/searches/ExponentialSearchTest.java b/src/test/java/com/thealgorithms/searches/ExponentialSearchTest.java index c84da531e8a4..c6b07ca2b4d5 100644 --- a/src/test/java/com/thealgorithms/searches/ExponentialSearchTest.java +++ b/src/test/java/com/thealgorithms/searches/ExponentialSearchTest.java @@ -81,4 +81,46 @@ void testExponentialSearchLargeArray() { int expectedIndex = 9999; assertEquals(expectedIndex, exponentialSearch.find(array, key), "The index of the last element should be 9999."); } + + /** + * An element sitting exactly on the doubling boundary used to be reported as missing, because + * the binary search was handed {@code range} as its exclusive upper bound instead of + * {@code range + 1}. + */ + @Test + void testExponentialSearchElementOnRangeBoundary() { + ExponentialSearch exponentialSearch = new ExponentialSearch(); + Integer[] array = {-25, -9, 8, 21}; + assertEquals(2, exponentialSearch.find(array, 8), "The index of the found element should be 2."); + } + + /** + * Every element must be found regardless of the array length. + */ + @Test + void testExponentialSearchFindsEveryElement() { + ExponentialSearch exponentialSearch = new ExponentialSearch(); + for (int length = 1; length <= 50; length++) { + Integer[] array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = i * 2; + } + for (int i = 0; i < length; i++) { + assertEquals(i, exponentialSearch.find(array, i * 2), "Element at index " + i + " should be found for length " + length + "."); + } + } + } + + /** + * A missing key has to yield -1 rather than the negative insertion point that + * {@link java.util.Arrays#binarySearch} returns. + */ + @Test + void testExponentialSearchNotFoundReturnsMinusOne() { + ExponentialSearch exponentialSearch = new ExponentialSearch(); + Integer[] array = {1, 3, 5, 7, 9, 11}; + assertEquals(-1, exponentialSearch.find(array, 4), "A key inside the range but absent should give -1."); + assertEquals(-1, exponentialSearch.find(array, 0), "A key below the minimum should give -1."); + assertEquals(-1, exponentialSearch.find(array, 12), "A key above the maximum should give -1."); + } }