Array Search in Plain English

When interacting with a data structure programmatically, you often carry out a read, search, insertion, or deletion operation. The time taken to complete each of these operations is dependent on the data structure and algorithm being used.

In this tutorial, you’ll learn how to search through a sorted array data structure using binary search in contrast with linear search algorithm. This tutorial won’t consider unsorted array edge cases.

Requirements

To follow along with this tutorial, you will need the following:

A search analogy

You’ve probably played a guessing game — where you guess a hidden number. If your guess is lower than the actual number, you receive a feedback stating “your guess is too low,” hinting you to guess a higher number. Conversely, if your guess is higher than the actual number, you receive a feedback stating “your guess is too high,” hinting you to guess a lower number accordingly.

Imagine two players playing our guessing game — player 1 is John and player 2 is Joe. The hidden number is 80 in a range of numbers between 1 to 80 — that is, 1,2,3,4,5,…,79,80

John decides to guess 1 as the hidden number. In a best-case scenario, John may be right. Assuming 1 isn’t the right guess, John tries 2 and continues this way till he guesses 80 to be the correct number.

Joe decides to get tricky and guesses the hidden number in halves — that is, Joe begins his guess with the mid-value in the given range. If the mid value isn’t the correct guess, the target value is either on the Left Hand Side (LHS) or Right Hand Side (RHS) of the range. Joe continues this way till he guesses the correct number.

John carried out a straight-line search that involved not jumping over any item, but going from the first to the last item in the given range successively. On the other hand, Joe carried out a voodoo search that involved dividing in halves. While both methods work, your goal is to efficiently search for an item in lesser time — even in a worst-case scenario.

The time complexity of a program is not an absolute measure of time taken (in seconds) for a program to carry out a task, but the steps taken to accomplish the task. It took John 80 steps (or guesses) to arrive at the hidden number.

Mimicking a search operation in computer memory

Limiting ourselves to the scope of this article, an array search operation can be done using either of the players’ approach. At the end of this section, you’ll learn how a computer plays the searching game using both approaches.

For this, we’ll represent an array of 6 items as a contiguous set of cells in a memory grid.

Let the sorted array be [1, 5, 8, 10, 18, 34] and target value be 34

Searching in a straight line

Let’s explore the operation in steps:

# Step 1: The computer is aware of the number of cells our array occupies in memory and starts by checking the first cell in the array against our target value of 34

1 is the item at the current cell being checked. 1 is less than or not equal to our guy. The search continues!

# Step 2: The current cell gets incremented by 1 to aid the computer in checking the next cell that follows for our target value.

5 is the item at the current cell being checked. 5 is less than or not equal to our guy. The search continues!

# Step 3: The current cell gets incremented by 1 to aid the computer in checking the next cell that follows for our target value.

8 is the item at the current cell being checked. 8 is less than or not equal to our guy. The search continues!

# Step 4: The current cell gets incremented by 1 to aid the computer in checking the next cell that follows for our target value.

10 is the item at the current cell being checked. 10 is less than or not equal to our guy. The search continues!

# Step 5: The current cell gets incremented by 1 to aid the computer in checking the next cell that follows for our target value.

18 is the item at the current cell being checked. 18 is less than or not equal to our guy. The search continues!

# Step 6: The current cell gets incremented by 1 to aid the computer in checking the next cell that follows for our target value.

34 is the item at the current cell being checked. 34 is equal to our guy. We’ve found our guy!

The computer searched and found the target value in six steps using the straight-line search — otherwise known as linear search. It took six steps while the array is sorted. What happens when the array isn’t sorted?

Searching in halves

You must be curious why Joe’s approach was termed a voodoo search.

Let’s explore the operation in steps:

# Step 1: The computer starts from the mid position in the array and checks if the value at the mid position is the target value.

midIndex = (startIndex + endIndex)/2 = 0+5/2 = 2.5 = 2

8 is the item at the current mid index which isn’t the target value. A decision must be made!

Since the item at the mid position isn’t the target value, a decision must be made on where next to search. Since 8 is less than 34, our target value is definitely on the RHS of the range. Due to this, everything on the LHS of the current mid position is discarded — as well as the current mid item.

At this point, the computer has updated the range (start index and end index) and must calculate a new mid index.

# Step 2: The computer calculates a new mid position based on the updated range in the diagram above.

midIndex = (startIndex + endIndex)/2 = 0+2/2 = 1

18 isn’t still our target value. A decision must be made!

Once again, we must decide on which direction to take our search. The item at the current mid index is 18 which is less than 34. Therefore, our target is at the RHS of our current mid index.

we’re now left with a single item that would either be our guy or not!

# Step 3: The computer calculates a new mid position based on the updated range. At this point, the start index and mid index are same — which is zero.

midIndex = (startIndex + endIndex)/2 = 0+0/2 = 0

The item at index 0 is 34 — which is our target value. The computer stops here and returns the original index of 34 in the original array as the result of search.

With the aid of searching in halves — otherwise known as binary search, the computer succeeded in finding the target value in just three steps. What happens when the array isn’t sorted?

Binary search algorithm only works on a sorted array data structure. In the case of an unsorted array, it becomes unclear if the target value is at the mid position, LHS, or RHS of the range.

When the array isn’t sorted, you can take advantage of the front and back algorithm that makes use of two iterators to find the target value quicker.

Alternatively, you could write a program that sorts the array before passing it into the binary search function.

Searching programmatically

Let the unsorted array be [5, 10, 1, 34, 18, 8], and target value be 9

Without crafting a program yet, it appears it would take the computer 6 steps to realize the target value isn’t even a member of the unsorted array. Do you agree?

What happen when the array is first sorted before being searched over in a linear manner? Would it have any impact on the number of steps before realization?

Before proceeding with the search, here is a global JavaScript function that can be used anywhere to sort an array in ascending order, using the bubble sort algorithm — which is beyond the scope of this article.

"use strict";

const handleNumberSort = (arr) => {
// Iterate through the array
for (let i = 0; i < arr.length - 1; i++) {
// Inner loop for comparison and swapping
for (let j = 0; j < arr.length - i - 1; j++) {
// Swap if the current element is greater than the next element
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // ES6 destructuring assignment
}
}
}
return arr; // Return the sorted array
};

console.log(handleNumberSort([5, 10, 1, 34, 18, 8])); // Output: [1, 5, 8, 10, 18, 34]

Right in your VS Code (or preferred IDE) terminal, cd into the directory containing the sort function and run the node <filename> command to confirm the function works as expected.

Replace <filename> with the actual name of file.

The result of running a sort function in a VS Code terminal

Since the computer needs to loop over every item in the array successively, a for loop is ideal in this case. It would also be great to have a condition that terminates the loop early enough when it’s clear the target value isn’t a member of the array.

"use strict";

const { handleNumberSort } = require("../sort/sort");

const findItemInArr = (arr, target) => {
for (let pointer = 0; pointer < arr.length; pointer++) {
console.log(
`Current iteration is ${pointer} || current iterated value is ${arr[pointer]}`
);
if (arr[pointer] === target) {
return pointer;
} else if (arr[pointer] > target) {
console.log(
`target doesn't exist in array => item at current iteration is greater than the target value of ${target}`
);
return -1;
}
}
};

console.log(findItemInArr(handleNumberSort([5, 10, 1, 34, 18, 8]), 9));

Run the node <filename> command to confirm the search function works as expected.

Logging the result of running the linear search function in the terminal

From the above screenshot, you can see that the loop terminated when 10 — being the value at the current iteration — is greater than the target value of 9

The else if block prevented the computer from taking two extra steps to realize the target value isn’t a member of the array. It’s worth noting that this approach worked because the array is sorted.

Below is a pseudocode for the binary search program:

  1. Receive a sorted array with N items and a target value

  2. Initialize mutable variables that hold the startIndex and stopIndex of the array respectively. Based on the start and stop index, the computer knows the total cells to search through at any given time. startIndex should be zero as an array is zero-based (or one-based if you write Lua). The stopIndex becomes the last index of the array — that is, sortedArray.length-1

  3. Inside a loop that continues running if there’s at least 1 item to search over, do the following:

  • Calculate the midIndex based on the start and stop index. That is, (startIndex+stopIndex)/2 — The value can’t be in decimal.

  • Check if the item at the current midIndex is equal to the target value. True? return the value from the binary search function.

  • Item at the current midIndex is less than the target value? discard items at the LHS of current midIndex by updating the range to become startIndex = midIndex + 1 (maintaining the stopIndex).

  • Item at the current midIndex is greater than the target value? discard items at the RHS of current midIndex by updating the range to become stopIndex = midIndex -1 (maintaining the startIndex).

4. If the loop terminates and target value isn’t found, return -1 from the binary search function.

Here’s an implementation of binary search in JavaScript:

const binarySearch = (sortedList, targetKey) => {
// initialize startIndex and stopIndex in the list
let startIndex= 0;
let stopIndex = sortedList.length - 1;

// the loop condition implies that the search would happen till there's no item left in the list/range
while (startIndex <= stopIndex) {
// trunc out the decimal part so midPosition matches existing positions in the list (since they are whole numbers)
let midPosition = Math.floor((startIndex + stopIndex) / 2);

if (sortedList[midPosition] === targetKey) {
return midPosition;
}

if (sortedList[midPosition] > targetKey) {
// an indication that the targetKey is at the LHS of midPosition
stopIndex = midPosition - 1;
} else {
// an indication that the targetKey is at the RHS of midPosition
startIndex = midPosition + 1;
}
}

return -1;
};

console.log(binarySearch(handleNumberSort([5, 10, 1, 34, 18, 8]), 9));

Logging the result of running the binary search function in the terminal

From the screenshot above, the search was conducted over three iterations. At the last iteration, 8 became the only element present in the array. Since 8 isn’t the target value, -1 is returned from the function.

Conclusion

This tutorial focused on exploring the binary and linear search algorithm using zero mathematical symbols and graph. Now would be a good time to research deeper, experiment more edge cases, and share personal findings with the community.

Vivek also made a list of some commonly asked interview questions that use binary search algorithm. Be sure to have some fun with them.

I’d be delighted to connect on LinkedIn. Cheers!