Lesson 25 of 50 intermediate

Binary Search — The Guessing Game

Find anything in a sorted collection blazingly fast

Open interactive version (quiz + challenge)

Real-world analogy

Imagine finding a word in a dictionary. You do not start from page 1 and read every page. Instead, you open the dictionary near the middle. If your word comes before the middle page, you look in the first half. If it comes after, you look in the second half. Each time you cut the remaining pages in half. That is binary search!

What is it?

Binary search is a divide-and-conquer algorithm that finds a target value within a sorted array. By comparing the target to the middle element and eliminating half the search space each time, it achieves O(log n) time complexity — meaning it can search through a billion elements in about 30 steps.

Real-world relevance

Binary search is used everywhere: database indexes find records in huge tables, version control 'git bisect' finds the commit that introduced a bug, spell checkers look up words in dictionaries, and even debugging uses binary search when you narrow down which half of the code contains the bug.

Key points

Code example

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    // Binary search in a sorted array
    int n, target;
    cin >> n >> target;
    vector<int> arr(n);
    for (int i = 0; i < n; i++) cin >> arr[i];

    int low = 0, high = n - 1;
    int result = -1; // -1 means not found

    while (low <= high) {
        int mid = low + (high - low) / 2; // Safe from overflow
        if (arr[mid] == target) {
            result = mid;
            break;
        } else if (arr[mid] < target) {
            low = mid + 1; // Target is in right half
        } else {
            high = mid - 1; // Target is in left half
        }
    }

    if (result != -1) {
        cout << "Found at index " << result << "\n";
    } else {
        cout << "Not found\n";
    }

    return 0;
}

Line-by-line walkthrough

  1. 1. int low = 0, high = n - 1; — low and high define our current search range. We start by searching the entire array from index 0 to index n-1.
  2. 2. int mid = low + (high - low) / 2; — we calculate the middle index. Using low + (high - low) / 2 instead of (low + high) / 2 prevents potential integer overflow.
  3. 3. if (arr[mid] == target) — if the middle element IS our target, we found it! Store the index and break out of the loop.
  4. 4. else if (arr[mid] < target) { low = mid + 1; } — if the middle element is smaller than our target, the target must be in the RIGHT half. We move low past mid to search only the right half.
  5. 5. else { high = mid - 1; } — if the middle element is larger than our target, the target must be in the LEFT half. We move high before mid to search only the left half.
  6. 6. while (low <= high) — we keep searching as long as our range is valid (low does not exceed high). If low becomes greater than high, the target is not in the array.

Spot the bug

#include <bits/stdc++.h>
using namespace std;

int main() {
    int arr[] = {1, 3, 5, 7, 9, 11};
    int n = 6, target = 7;
    int low = 0, high = n;
    int result = -1;

    while (low <= high) {
        int mid = (low + high) / 2;
        if (arr[mid] == target) {
            result = mid;
            break;
        } else if (arr[mid] < target) {
            low = mid;
        } else {
            high = mid;
        }
    }

    cout << "Found at index: " << result << "\n";
    return 0;
}
Need a hint?
There are two problems. First, look at the initial value of high — is arr[n] a valid index? Second, when we update low and high, could the loop get stuck if mid never changes?
Show answer
Two bugs! First, high should be n-1, not n. arr[6] is out of bounds for an array of size 6. Second, low = mid and high = mid can cause an infinite loop — when low and high differ by 1, mid equals low, so low = mid never changes. Fix: use low = mid + 1 and high = mid - 1 to guarantee the range shrinks each step.

Explain like I'm 5

Imagine you are playing a guessing game. I am thinking of a number between 1 and 100. Every time you guess, I tell you if the real number is bigger or smaller. What is the best strategy? Always guess the middle! If I say 'bigger,' you only look at the top half. If 'smaller,' only the bottom half. Each guess throws away HALF the numbers. In just 7 guesses, you can find any number from 1 to 100. That is binary search — always pick the middle and cut your problem in half!

Fun fact

Binary search is so powerful that if you had a sorted list of every person on Earth (8 billion people), you could find any specific person in at most 33 comparisons. That is roughly the same number of guesses it takes to find a number between 1 and 8 billion! The idea dates back to 1946, but the first bug-free binary search was not published until 1962 — it is deceptively tricky to get right.

Hands-on challenge

Write a binary search program that not only finds whether the target exists, but also prints each step of the search (the current low, high, mid, and the comparison result). Test with a sorted array [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] and search for 23. How many steps did it take?

More resources

Open interactive version (quiz + challenge) ← Back to course: CP Zero to Hero