Binary Search

Say you have a list of a million sorted numbers. You need to find one of them. Checking each number one by one is slow. You might look at almost the whole list before you find it. Binary search fixes that pain. It throws away half the list on every single check. So a million numbers takes only about twenty looks.

Binary search is a way to find a value in a sorted array fast. Sorted means the values are already in order. They go from smallest to largest.

The idea is simple. You look at the middle value first. Then you ask one question. Is my target smaller or bigger than this middle?

  • If the target is smaller, it must be on the left side. So you ignore the right half.
  • If the target is bigger, it must be on the right side. So you ignore the left half.
  • If the middle is exactly your target, you are done.

Every check cuts the remaining numbers in half. That is why it is so fast.

πŸ“š A Real-World Analogy

Think about finding a word in a paper dictionary. You don’t start at page one and read every word. That would take forever.

Instead you open the dictionary somewhere in the middle. Say you are looking for β€œmango”. You land on a page with β€œrabbit”. Now β€œmango” comes before β€œrabbit”. So you flip to the left half. You open the middle of that half and land on β€œgarden”. This time β€œmango” comes after β€œgarden”. So you jump to the right. You keep splitting like this until you land on the page with β€œmango”.

That is binary search. A dictionary only works this way because the words are in order. The same rule applies here. The array must be sorted first. If it is not, binary search gives wrong answers.

Caution

Binary search only works on a sorted array. If the array is not in order, the left-or-right decision means nothing. You will miss your target. So sort the array first, or use linear search instead.

πŸ” How It Works

We keep two markers. One is low. It marks the start of the part we are still searching. The other is high. It marks the end of that part. At the start, low is the first index and high is the last index.

Then we repeat these moves. We stop when we find the target or run out of range.

  • Find the middle index: mid = (low + high) / 2.
  • Look at arr[mid].
  • If arr[mid] equals the target, return mid. We found it.
  • If the target is smaller than arr[mid], the answer is on the left. Set high = mid - 1.
  • If the target is bigger than arr[mid], the answer is on the right. Set low = mid + 1.

When does it stop? It stops when low becomes greater than high. That means the range is empty and the target is not there. So we return -1.

Here is the whole flow as a picture.

No

Yes

Yes

No

Yes

No

Set low = 0, high = last index

low less than or equal to high?

Return -1, not found

mid = low + high / 2

arr at mid equals target?

Return mid

target less than arr at mid?

high = mid - 1

low = mid + 1

Let’s trace a quick example. Say the array is [2, 5, 8, 12, 16, 23, 38, 56] and we want 23.

Step low high mid arr[mid] Decision
1 0 7 3 12 23 is bigger, go right
2 4 7 5 23 Match. Return 5

Two checks and we found it. A linear scan would have taken six.

Before we write code, let’s list the steps in order.

  1. Set low to 0 and high to the last index of the array.
  2. Repeat while low is less than or equal to high.
  3. Calculate mid as low + (high - low) / 2.
  4. If arr[mid] equals the target, return mid.
  5. If the target is greater than arr[mid], set low = mid + 1.
  6. If the target is smaller than arr[mid], set high = mid - 1.
  7. If the loop ends without a match, return -1.

Tip

Notice we write mid = low + (high - low) / 2 instead of (low + high) / 2. Both give the same middle. But for very large arrays, low + high can overflow and become a wrong number. The first form avoids that. It is a small habit that saves you from a nasty bug.

πŸ’» Binary Search in Code

Now let’s write binarySearch(arr, target). It returns the index where the target sits. If the target is not in the array, it returns -1. The array is already sorted.

binary_search.py
def binary_search(arr, target):
"""Return the index of target in a sorted list, or -1 if not found."""
low = 0
high = len(arr) - 1
while low <= high:
mid = low + (high - low) // 2 # safe middle
if arr[mid] == target:
return mid # found it
elif target > arr[mid]:
low = mid + 1 # go right
else:
high = mid - 1 # go left
return -1 # not found
arr = [2, 5, 8, 12, 16, 23, 38, 56]
print("Index of 23:", binary_search(arr, 23))
print("Index of 5:", binary_search(arr, 5))
print("Index of 100:", binary_search(arr, 100))

The output of the above code will be:

Index of 23: 5
Index of 5: 1
Index of 100: -1

Note

Time complexity is O(log n). Each loop throws away half the remaining elements. So the work grows very slowly even as the array gets huge. Space complexity is O(1). We only use a few variables like low, high, and mid. We never make a copy of the array.

⏱️ Complexity Summary

Here is how binary search compares. This shows you why it shines on big sorted arrays.

Case Time When It Happens
Best case O(1) Target sits right at the middle on the first check
Average case O(log n) Target is found after a few halvings
Worst case O(log n) Target is missing or sits at the very edge
Space O(1) Only a few index variables, no extra array

To feel the difference, think about a million items. Linear search can take a million checks. Binary search takes about twenty. That is the gift of halving.

⚠️ Common Mistakes

A few things trip people up the first time.

  • Running binary search on an array that is not sorted. The left-or-right choice only makes sense in order. So you get wrong answers.
  • Writing low < high instead of low <= high. With the wrong sign you can skip the last element. Then you miss a target that is really there.
  • Forgetting to move low or high. If you don’t shrink the range, the loop never ends.
  • Using (low + high) / 2 on very large arrays. The sum can overflow. Use low + (high - low) / 2 to stay safe.

🧩 What You’ve Learned

βœ… Binary search finds a value in a sorted array. It checks the middle and cuts the range in half each time.

βœ… You keep two markers, low and high. You move them based on whether the target is smaller or bigger than the middle.

βœ… It runs in O(log n) time and O(1) space. So it stays fast even on huge arrays.

βœ… The array must be sorted first, or the result is wrong. Use linear search if the data is not in order.

βœ… Use low + (high - low) / 2 for the middle. This avoids overflow on large arrays.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What is the one condition the array must meet for binary search to work correctly?

    Why: Binary search decides to go left or right based on order, so the array has to be sorted first.

  2. 2

    What is the time complexity of binary search?

    Why: Each step removes half of the remaining elements, which gives O(log n) time.

  3. 3

    If the target is smaller than arr[mid], what should you do?

    Why: A smaller target must be on the left, so you move high to mid - 1 and search that half.

  4. 4

    Why prefer mid = low + (high - low) / 2 over (low + high) / 2?

    Why: Adding low + high directly can overflow for large indices, while the other form stays within safe range.

πŸš€ What’s Next?

Share & Connect