diff --git a/src/algorithms/search/exponential-search/README.md b/src/algorithms/search/exponential-search/README.md new file mode 100644 index 00000000..f0f7b7d0 --- /dev/null +++ b/src/algorithms/search/exponential-search/README.md @@ -0,0 +1,16 @@ +# Exponential Search + +In computer science, an exponential search is an algorithm.There are numerous ways to implement this with the most common being to determine a range that the search key +resides in and performing a binary search within that range. This takes O(log i) where i is the position of the search key in the list, if the search key is in the list, +or the position where the search key should be, if the search key is not in the list.Exponential search can also be used to search in bounded lists. Exponential search +can even out-perform more traditional searches for bounded lists, such as binary search, when the element being searched for is near the beginning of the array. + +![Exponential Search](https://upload.wikimedia.org/wikipedia/commons/4/45/Exponential_search.svg) + +## Complexity + +**Time Complexity**: `O(log i)` - i is the index of the element being searched for in the list + +## References + +-[Wikipedia](https://en.wikipedia.org/wiki/Exponential_search) diff --git a/src/algorithms/search/exponential-search/__test__/exponentialSearch.test.js b/src/algorithms/search/exponential-search/__test__/exponentialSearch.test.js new file mode 100644 index 00000000..0816af2b --- /dev/null +++ b/src/algorithms/search/exponential-search/__test__/exponentialSearch.test.js @@ -0,0 +1,35 @@ +import exponentialSearch from '../exponentialSearch'; + +describe('exponentialSearch', () => { + it('should search number in sorted array', () => { + expect(exponentialSearch([], 1)).toBe(-1); + expect(exponentialSearch([1], 1)).toBe(0); + expect(exponentialSearch([1, 2], 1)).toBe(0); + expect(exponentialSearch([1, 2], 2)).toBe(1); + expect(exponentialSearch([1, 5, 10, 12], 1)).toBe(0); + expect(exponentialSearch([1, 5, 10, 12, 14, 17, 22, 100], 17)).toBe(5); + expect(exponentialSearch([1, 5, 10, 12, 14, 17, 22, 100], 1)).toBe(0); + expect(exponentialSearch([1, 5, 10, 12, 14, 17, 22, 100], 100)).toBe(7); + expect(exponentialSearch([1, 5, 10, 12, 14, 17, 22, 100], 0)).toBe(-1); + }); + + it('should search object in sorted array', () => { + const sortedArrayOfObjects = [ + { key: 1, value: 'value1' }, + { key: 2, value: 'value2' }, + { key: 3, value: 'value3' }, + { key: 4, value: 'value4' }, + ]; + + const comparator = (a, b) => { + if (a.key === b.key) return 0; + return a.key < b.key ? -1 : 1; + }; + + expect(exponentialSearch([], { key: 1 }, comparator)).toBe(-1); + expect(exponentialSearch(sortedArrayOfObjects, { key: 4 }, comparator)).toBe(3); + expect(exponentialSearch(sortedArrayOfObjects, { key: 1 }, comparator)).toBe(0); + expect(exponentialSearch(sortedArrayOfObjects, { key: 2 }, comparator)).toBe(1); + expect(exponentialSearch(sortedArrayOfObjects, { key: 3 }, comparator)).toBe(2); + }); +}); diff --git a/src/algorithms/search/exponential-search/exponentialSearch.js b/src/algorithms/search/exponential-search/exponentialSearch.js new file mode 100644 index 00000000..7d6b3c56 --- /dev/null +++ b/src/algorithms/search/exponential-search/exponentialSearch.js @@ -0,0 +1,56 @@ +import Comparator from '../../../utils/comparator/Comparator'; + +/** + * Binary search implementation. + * + * @param {*[]} sortedArray + * @param {*} startIndex + * @param {*} endIndex + * @param {*} seekElement + * @param {function(a, b)} [comparatorCallback] + * @return {number} + */ + +function binarySearch(sortedArray, startIndex, endIndex, seekElement, comparatorCallback) { + const comparator = new Comparator(comparatorCallback); + if (endIndex >= startIndex) { + const middleIndex = startIndex + Math.floor((endIndex - startIndex) / 2); + // If the element is present at the middle itself + if (comparator.equal(sortedArray[middleIndex], seekElement)) { + return middleIndex; + } + // If element is smaller than middleIndex, then it can only be present n left subarray + if (comparator.greaterThan(sortedArray[middleIndex], seekElement)) { + return binarySearch(sortedArray, startIndex, middleIndex - 1, seekElement, comparatorCallback); + } + // Else the element can only be present in right subarray + return binarySearch(sortedArray, middleIndex + 1, endIndex, seekElement, comparatorCallback); + } + // We reach here when element is not present in array + return -1; +} +/** + * Exponential search implementation. + * + * @param {*[]} sortedArray + * @param {*} seekElement + * @param {function(a, b)} [comparatorCallback] + * @return {number} + */ +export default function exponentialSearch(sortedArray, seekElement, comparatorCallback) { + const comparator = new Comparator(comparatorCallback); + const length = sortedArray.length; + // If element is present at first location itself + if (sortedArray.length !== 0) { + if (comparator.equal(sortedArray[0], seekElement)){ + return 0; + } + } + // Find range for binary search by repeated doubling + let range = 1; + while (range < length && comparator.lessThanOrEqual(sortedArray[range], seekElement)) { + range *= 2; + } + // Call binary search for the found range. + return binarySearch(sortedArray, range/2, Math.min(range, length - 1), seekElement, comparatorCallback); +}