ALGORITHMS: Implementing Binary Search Algorithm in Javascript

ALGORITHMS: Implementing Binary Search Algorithm in Javascript

Introduction

Imagine searching for a word in a dictionary. Would you flip through every single page? Or would you use a smarter approach, like opening to the middle to quickly narrow down where that word might be? This is the elegant power of binary search. An algorithm that can find what you need in a billon items with just 30 simple steps.

Searching is fundamental in programming because it lets us find and retrieve specific data from large collections - whether that's finding a user account in a database, locating items in an inventory system, or checking if a word exists in a dictionary. Without efficient search, many everyday applications we rely on would be impractically slow.

Binary search is a clever algorithm that takes advantage of sorted data to dramatically speeds up searching. Instead of checking every element one by one, it repeatedly divides the search space in half with each iteration. This is kind of like guessing a number when someone says "higher" or "lower." This lets it find items in a sorted list of 1 billion elements in just 30 steps or less, compared to potentially 1 billion steps for a basic linear search.

Prerequisites

To understand this topic, you just need to know basic algebra. For example, look at this function f(x) = x/3. What is f(21)? If your answer is 7 then you are ready. You also need to know at least one programming language. I will be using javascript in this article.

How Binary Search Works

The binary search algorithm is an algorithm that takes an input of sorted elements(important), searches through it and returns the position of the target value.

Suppose you are searching for a word in the dictionary. The word starts with the letter ‘O’. You could start at the beginning and keep flipping the pages of the dictionary till you get to the words that begin with O. This doesn’t sound practical. This method of searching is called simple search (more on this later). You are most likely to start at a random page in the middle because you know the Os are going to be close to the middle of the dictionary.

Essentially, if you are looking for the word “opportunity” in the dictionary, you know that the word cannot be between A and N and so you divide your search space into two parts, removing A to N. You do this again until you get to the address of the word “opportunity” in the dictionary or stop searching if the word is not found in the dictionary.

In other words, we can break down this algorithm into 3 process:

  • Find the middle element.

  • Decide which half to search next.

  • Repeat until the target is found or the target is not found.

Key Requirements

The main requirement for binary search to work is sorted input. This is because, the algorithm relies on being able to eliminate half of the remaining elements, because it knows exactly where the target must be based on the sorted order. Think of it like having a dictionary with 100 pages and looking for the word “opportunity”. If you open to page 50 and see “render”, you instantly know “opportunity” must be in the first half because O comes before R in the alphabetical order. You have just eliminated 50 pages! Then you can open to page 25, and if you see the word “lion”, you know “opportunity” must be in the second quarter (pages 25 -50), because O comes after L in the alphabetic order. Each comparison lets you cut your search area in half, making the process very efficient.

If the data weren’t sorted, seeing the word “render” on page 50 wouldn’t give you any useful clue as to where the word “opportunity” might be. It could be anywhere before or after that page.

Pseudo Code

Input

  • array: a sorted array of elements

  • target: the element to be searched

Output

  • index: the index(position) of the target element if found, -1 otherwise
PROCEDURE binary_search(array, target)
    low = 0
    high = array.length -1

    WHILE low <= high
        mid = (low + high)/2
        guess = array[mid]

        IF guess > target 
            high = mid - 1;
        ELSE IF guess < target
            low = mid + 1
        ELSE 
            return mid
    RETURN -1

Code implementation in JavaScript

const binary_search = (array, target) => {
    // set the two pointers
    let high_point = array.length - 1;
    let low_point = 0;

    while (low_point <= high_point) {
        let mid_point = Math.floor((high_point + low_point) / 2);
        let guess = array[mid_point];

        if (guess > target) {
            high_point = mid_point - 1;
        } else if (guess < target) {
            low_point = mid_point + 1
        } else {
            return mid_point
        } 
    }

  return -1;
}

const the_array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(binary_search(the_array, 14)); // returns -1
console.log(binary_search(the_array, 7)); // returns 6

Time Complexity

💡
whenever you see log X in this article, think of it as log x in base 2.

The time complexity of the binary search algorithm is O(log n), this is knows as log time. Like we saw earlier, each step eliminates half of the search space. For example, in a sorted array of 1024 elements, you would need at most 10 steps to find any element(this is because log 1024 = 10 or 2^10 = 1024), because each comparison divides the search space in half. Even if the size of the array doubles, to 2048 elements, it will only take 11 steps to find an element in the worst case. This logarithmic growth makes binary search highly efficient for large datasets.

Linear search on the other hand, has a time complexity of O(n). This is because, linear or simple search checks each element in the list sequentially, from start to finish, until the target is found or the list ends. In an array of 1024 elements, you may need all 1024 steps in the worst case. If the array size doubles, you may need to check all 2048 elements; the maximum steps also double. This means that its time complexity worsens linearly with the size of the list.

To put this in perspective: for a billon elements, the maximum steps a linear search might need will be 1,000,000,000 steps, while binary search will only need about 30 steps (log 21,000,000,000 =29.9). This emphatic difference makes binary search far more efficient for large sorted datasets.

Application of This Algorithm

Let us look at some real world examples that shows how invaluable the binary search algorithm is.

  • Database systems: in database systems, binary search forms the foundation of index lookups. When you search for a specific user_id in a database with millions of records, the database engine uses binary search on sorted indexes to quickly locate relevant data. Rather than scanning through every record, it can find any entry in just a few steps, enabling near instant query responses we expect from modern applications.

  • Financial systems: financial systems use binary search for real-time stock price lookups. When you're tracking price movements throughout a trading day, binary search helps locate specific price points in time-series data. This is crucial for high-frequency trading systems where microseconds matter.

  • Version control systems: Git's bisect command uses binary search to find which commit introduced a bug by testing midpoints between known good and bad commits. By systematically testing the midpoint between known good and bad commits, developers can identify problematic changes in large codebases remarkably quickly.

  • E-commerce platforms: e-commerce platforms heavily rely on binary search when displaying product catalogs. When a customer filters products by price range, say $10-$20, the system can quickly find the starting and ending points of this range in a sorted price list. This explains why price filtering on sites like Amazon feels so responsive even with millions of products.

Beyond these examples, binary search's efficiency makes it a fundamental building block in countless algorithms and systems where quick lookup in sorted data is needed.

Conclusion

Binary search is a fundamental algorithm that transforms O(n) operations into O(log n), making it essential for handling large-scale data efficiently. By repeatedly dividing the search space in half, it can find elements in massive datasets with remarkably few steps. Just 20 comparisons for a million items versus potentially a million checks with linear search.

Its applications span from database indexing to Git version control, demonstrating its practical value beyond theoretical computer science.

To truly understand its power, implement binary search on different problems:

  • Start with basic sorted array searches

  • Try finding square roots using binary search

  • Implement more complex applications like rate limiters

  • Use git bisect on a real project to find bugs

The effort invested in mastering binary search pays dividends throughout your programming career, as its principles apply to numerous optimization problems and system designs.