Skip to content

Commit

Permalink
Add Interpolation Search.
Browse files Browse the repository at this point in the history
  • Loading branch information
trekhleb committed Jul 18, 2018
1 parent 31344fa commit 149444b
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ a set of rules that precisely define a sequence of operations.
* `B` [Linear Search](src/algorithms/search/linear-search)
* `B` [Jump Search](src/algorithms/search/jump-search) (or Block Search) - search in sorted array
* `B` [Binary Search](src/algorithms/search/binary-search) - search in sorted array
* `B` [Interpolation Search](src/algorithms/search/interpolation-search) - search in uniformly distributed sorted array
* **Sorting**
* `B` [Bubble Sort](src/algorithms/sorting/bubble-sort)
* `B` [Selection Sort](src/algorithms/sorting/selection-sort)
Expand Down
40 changes: 40 additions & 0 deletions src/algorithms/search/interpolation-search/README.md
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)
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 src/algorithms/search/interpolation-search/interpolationSearch.js
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;
}
2 changes: 1 addition & 1 deletion src/algorithms/search/jump-search/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ minimum when `m = √n`. Therefore, the best step size is `m = √n`.

## References

- [Wikipedia](https://en.wikipedia.org/wiki/Jump_search)
- [GeeksForGeeks](https://www.geeksforgeeks.org/jump-search/)
- [Wikipedia](https://en.wikipedia.org/wiki/Jump_search)
2 changes: 1 addition & 1 deletion src/algorithms/search/jump-search/jumpSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Comparator from '../../../utils/comparator/Comparator';
/**
* Jump (block) search implementation.
*
* @param {*[]} sortedArray.
* @param {*[]} sortedArray
* @param {*} seekElement
* @param {function(a, b)} [comparatorCallback]
* @return {number}
Expand Down

0 comments on commit 149444b

Please sign in to comment.