Add exponential search

This commit is contained in:
GohJunLe 2022-09-03 12:38:31 +08:00 committed by GitHub
parent 2913a98023
commit 1baf6106fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 106 additions and 0 deletions

View File

@ -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)

View File

@ -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);
});
});

View File

@ -0,0 +1,55 @@
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 = range * 2;
}
// Call binary search for the found range.
return binarySearch(sortedArray, range/2, Math.min(range, length - 1), seekElement, comparatorCallback);
}