Merge pull request #1 from GohJunLe/GohJunLe-patch-1

Add exponential search
This commit is contained in:
GohJunLe 2022-08-09 08:37:29 +08:00 committed by GitHub
commit 6197291277
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 0 deletions

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,67 @@
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{
// 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);
}