forked from trekhleb/javascript-algorithms
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
119 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Interpolation Search | ||
|
||
**Interpolation search** is an algorithm for searching for a key in an array that | ||
has been ordered by numerical values assigned to the keys (key values). | ||
|
||
For example we have a sorted array of `n` uniformly distributed values `arr[]`, | ||
and we need to write a function to search for a particular element `x` in the array. | ||
|
||
**Linear Search** finds the element in `O(n)` time, **Jump Search** takes `O(√ n)` time | ||
and **Binary Search** take `O(Log n)` time. | ||
|
||
The **Interpolation Search** is an improvement over Binary Search for instances, | ||
where the values in a sorted array are _uniformly_ distributed. Binary Search | ||
always goes to the middle element to check. On the other hand, interpolation | ||
search may go to different locations according to the value of the key being | ||
searched. For example, if the value of the key is closer to the last element, | ||
interpolation search is likely to start search toward the end side. | ||
|
||
To find the position to be searched, it uses following formula: | ||
|
||
``` | ||
// The idea of formula is to return higher value of pos | ||
// when element to be searched is closer to arr[hi]. And | ||
// smaller value when closer to arr[lo] | ||
pos = lo + ((x - arr[lo]) * (hi - lo) / (arr[hi] - arr[Lo])) | ||
arr[] - Array where elements need to be searched | ||
x - Element to be searched | ||
lo - Starting index in arr[] | ||
hi - Ending index in arr[] | ||
``` | ||
|
||
## Complexity | ||
|
||
**Time complexity**: `O(log(log(n))` | ||
|
||
## References | ||
|
||
- [GeeksForGeeks](https://www.geeksforgeeks.org/interpolation-search/) | ||
- [Wikipedia](https://en.wikipedia.org/wiki/Interpolation_search) |
24 changes: 24 additions & 0 deletions
24
src/algorithms/search/interpolation-search/__test__/interpolationSearch.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import interpolationSearch from '../interpolationSearch'; | ||
|
||
describe('interpolationSearch', () => { | ||
it('should search elements in sorted array of numbers', () => { | ||
expect(interpolationSearch([], 1)).toBe(-1); | ||
expect(interpolationSearch([1], 1)).toBe(0); | ||
expect(interpolationSearch([1], 0)).toBe(-1); | ||
expect(interpolationSearch([1, 1], 1)).toBe(0); | ||
expect(interpolationSearch([1, 2], 1)).toBe(0); | ||
expect(interpolationSearch([1, 2], 2)).toBe(1); | ||
expect(interpolationSearch([10, 20, 30, 40, 50], 40)).toBe(3); | ||
expect(interpolationSearch([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 14)).toBe(13); | ||
expect(interpolationSearch([1, 6, 7, 8, 12, 13, 14, 19, 21, 23, 24, 24, 24, 300], 24)).toBe(10); | ||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 600)).toBe(-1); | ||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 1)).toBe(0); | ||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 2)).toBe(1); | ||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 3)).toBe(2); | ||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 700)).toBe(3); | ||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 800)).toBe(4); | ||
expect(interpolationSearch([0, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 1200)).toBe(5); | ||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 19000], 800)).toBe(4); | ||
expect(interpolationSearch([0, 10, 11, 12, 13, 14, 15], 10)).toBe(1); | ||
}); | ||
}); |
52 changes: 52 additions & 0 deletions
52
src/algorithms/search/interpolation-search/interpolationSearch.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/** | ||
* Interpolation search implementation. | ||
* | ||
* @param {*[]} sortedArray - sorted array with uniformly distributed values | ||
* @param {*} seekElement | ||
* @return {number} | ||
*/ | ||
export default function interpolationSearch(sortedArray, seekElement) { | ||
let leftIndex = 0; | ||
let rightIndex = sortedArray.length - 1; | ||
|
||
while (leftIndex <= rightIndex) { | ||
const rangeDelta = sortedArray[rightIndex] - sortedArray[leftIndex]; | ||
const indexDelta = rightIndex - leftIndex; | ||
const valueDelta = seekElement - sortedArray[leftIndex]; | ||
|
||
// If valueDelta is less then zero it means that there is no seek element | ||
// exists in array since the lowest element from the range is already higher | ||
// then seek element. | ||
if (valueDelta < 0) { | ||
return -1; | ||
} | ||
|
||
// If range delta is zero then subarray contains all the same numbers | ||
// and thus there is nothing to search for unless this range is all | ||
// consists of seek number. | ||
if (!rangeDelta) { | ||
// By doing this we're also avoiding division by zero while | ||
// calculating the middleIndex later. | ||
return sortedArray[leftIndex] === seekElement ? leftIndex : -1; | ||
} | ||
|
||
// Do interpolation of the middle index. | ||
const middleIndex = leftIndex + Math.floor(valueDelta * indexDelta / rangeDelta); | ||
|
||
// If we've found the element just return its position. | ||
if (sortedArray[middleIndex] === seekElement) { | ||
return middleIndex; | ||
} | ||
|
||
// Decide which half to choose for seeking next: left or right one. | ||
if (sortedArray[middleIndex] < seekElement) { | ||
// Go to the right half of the array. | ||
leftIndex = middleIndex + 1; | ||
} else { | ||
// Go to the left half of the array. | ||
rightIndex = middleIndex - 1; | ||
} | ||
} | ||
|
||
return -1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters