Searching Algorithms in JavaScript - The Definitive Guide
COVERS LINEAR, BINARY, JUMP, INTERPOLATION AND EXPONENTIAL SEARCH.
Searching means locating a particular element in a collection of elements. The search result determines whether that particular element is present in the collection or not. If it is present, we can also find out the position of that element in the given collection.
Searching is an essential technique in computer science. A computer stores lots of data to be retrieved later as demanded by a user or a program. To design algorithms, we need to understand the different ways a collection of data can be searched for retrieval.
Without further ado, let’s learn different search techniques.
Linear Search:
It is the most fundamental searching technique.
Every element of the array is compared to the key element (the element that has to be found). If the element is found in the array then return its index. Otherwise, return -1.
It is also referred to as a sequential search.
This technique is useful for a collection of items that are small in size and unordered.
Algorithm:
Note: let the element to be found is x
Start from the leftmost element of the array and one by one compare x with each element of the array.
If x matches with an element return its
index
.If x is not found in the array return
-1
.
Time Complexity: O(N)
Space Complexity: O(1)
Note: Best Case is when the element (to be found) is at the 0th index
and the Worst Case is when the element is not present in the array.
Binary Search:
Binary Search is a searching algorithm used in a sorted array by repeatedly dividing the search interval in half. The idea of binary search is to use the information that the array is sorted and reduce the time complexity to O(log n).
The binary search runs in logarithmic time in the worst case, making O(logN) comparisons, where n is the number of elements in the array.
Binary search is faster than linear search except for small arrays. However, the array must be sorted first to be able to apply binary search.
Algorithm:
Find the mid element of the array and compare it with the target value.
If the value of the mid element and target are the same, return the
index of mid
.If the mid-value is greater than the target, search in the
lower half of the array
.Otherwise, search in the
upper half of the array
.If the target value is not found then return -1.
Iterative Binary Search
Recursive Binary Search
Time Complexity: O(logN)
Space Complexity: O(1)
Note:
To find the
mid
the value we have used is the floor value of(start + end) / 2
It’s important to note that it fails for larger values of int variables
start
andend
. Specifically, it fails if the sum ofstart
andend
is greater than the maximum positive int value (2³¹-1).The sum overflows to a negative value and the value stays negative when divided by 2.
So it’s better to find out the mid-value like this…
mid = start + (end - start) / 2;
Jump Search:
Like Binary Search, Jump Search is a searching algorithm for sorted arrays. The basic idea is to check fewer elements (than linear search) by jumping ahead by fixed steps or skipping some elements in place of searching all elements.
The jump is also referred to as the block size.
The optimal size of a block to be jumped is (√ n).
Why Jump Search?
Binary Search is better than Jump Search, but Jump Search has the advantage that we traverse back only once (Binary Search may require up to O(Log n) jumps, consider a situation where the element to be searched is the smallest element or just bigger than the smallest). So, we use Jump Search in a system where the binary search is costly.
Algorithm:
Find the block size to be jumped.
Find the block where the element is present (if present).
Do the linear search for the target in the block where the target could be present.
If we reached the next block or the end of the array, the element is not present.
If the element is found, return the index.
Else return -1.
Time Complexity: O(√N)
Note: The optimal size of a block to be jumped is (√N). This makes the time complexity of Jump Search O(√N).
Space Complexity: O(1)
Interpolation Search:
Interpolation search is an algorithm similar to the binary search for searching for a given target value in a sorted array.
Interpolation constructs new data points within the range of a discrete set of known data points. 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.There are three main things to remember when doing an interpolation search:
1. Given: Sorted array of n uniformly distributed values.
2. Goal: Search for the target element(x).
3. Formula:
pos = low + ((x - a[low]) * (high - low)) / (a[high] - a[low])
a: array where the element needs to be searched.
pos: index where the target element could be present.
low: the value of the left index (starting index).
high: the value of the right index (ending index).
a[low]: the element of array a at low index.
a[high]: the element of array a at high index.
Algorithm:
Initialise
n = size
of the array,low = 0, high = n-1
. We will use low and high to determine the left and right ends of the array in which we will be searching at any given time.If
low > high
, it means we have exhausted the array and we could not find K. We return -1 to signify that the element k was not found.If
k < arr[low] || k > arr[high]
, it means k is either less than the smallest element or greater than the largest element of the current array and since the array is sorted, we will never be able to find k in this array. Hence, we return -1 to signify that the element k was not found.Else
low <= high
, and we apply the interpolation equation to find the index where we should start the search from, as follows:
Find pos (position) using the formula
pos = low + (k - arr[low]) * (high - low) / (arr[high] — arr[low])
if
arr[pos] < k
, it means the element at the current index is less than k. So set the value of low topos + 1
if
arr[pos] > k
, it means the element at the current index is greater than k. So set the value of high topos - 1
else
arr[pos] == k
, return pos
Time Complexity:
If the array is sorted and uniformly distributed: O(log(log(N)))
If the array is sorted but not uniformly distributed: O(N)
Space Complexity: O(1)
Exponential Search:
Exponential search is an algorithm used for searching sorted, unbounded/infinite lists. It searches for an element in a sorted array by jumping
2^i
elements every iteration wherei
represents the value of the loop control variable and then verifies if the search element is present between the last jump and the current jump.It was created by Jon Bentley and Andrew Chi-Chih Yao in 1976.
Exponential search can also be used to search in bounded lists.
It can even outperform more traditional searches for bounded lists, such as binary search, when the element being searched for is near the beginning of the array. This is because the exponential search will run in O(log i) time, where i is the index of the element being searched for in the list, whereas the binary search would run in O(log n) time, where n is the number of elements in the list.
Algorithm:
Jump the array
2^i
elements at a time searching for the conditionarray[2^(i-1)] < target < array[2^i]
. If2^i
is greater than the length of the array, then set the upper bound to the length of the array.Do a binary search between
array[2^(i-1)]
andarray[2^i]
.
Time Complexity: O(log N)
Space Complexity:
If an iterative binary search is used: O(1)
If a recursive binary search is used: O(log N)
References: