Stage 1: Foundations·Binary Search Mastery
Easy#7045 min readBinary SearchArraysLeetCode

Binary Search

Classic binary search

Get the template perfect: lo, hi, mid, and the loop condition. Practice until it’s automatic.

Published Apr 15, 2026

Problem

Given a sorted array nums and a target value target, return the index of target if it exists. Otherwise return -1.

The input is strictly sorted in ascending order, so every comparison tells you which half can be discarded.

Input
nums = [-1, 0, 3, 5, 9, 12], target = 9
Output
4
Input
nums = [-1, 0, 3, 5, 9, 12], target = 2
Output
-1
Explanation
2 never appears, so the search interval collapses without a match.

Intuition

Binary search is not "search in a sorted array" so much as "repeatedly destroy half of the remaining search space without losing correctness."

The key invariant is simple:

  • if target exists, it is always inside the current interval;
  • every comparison with nums[mid] lets us rule out one half immediately.

The cleanest implementation uses a half-open interval [lo, hi). That avoids off-by-one bugs and makes the termination condition obvious: once lo == hi, the interval is empty.

Approach

Half-Open Binary Search

TimeO(log n)
SpaceO(1)
Recommended

Keep the candidate interval as [lo, hi). Compare nums[mid] with target:

  • If nums[mid] < target, the answer must be to the right, so move lo to mid + 1.
  • If nums[mid] > target, the answer must be to the left, so move hi to mid.
  • If equal, return immediately.

When the loop ends, the interval is empty and the target was never found.

impl Solution {
    pub fn search(nums: Vec<i32>, target: i32) -> i32 {
        let mut lo = 0usize;
        let mut hi = nums.len();

        while lo < hi {
            let mid= lo + (hi - lo) / 2;
            if nums[mid] < target {
                lo= mid + 1;
            } else if nums[mid] > target {
                hi = mid;
            } else {
                return mid as i32;
            }
        }

        -1
    }
}
Rust · runnable

Trace

Searching for target = 9 in nums = [-1, 0, 3, 5, 9, 12]:

lohimidnums[mid]action
0635move lo to 4
46512move hi to 5
4549return 4

Each step discards exactly half of the remaining interval.

Edge cases

  • Empty array — the loop never runs; return -1.
  • Single element — either return index 0 or -1 after one comparison.
  • Target smaller than all values or larger than all values — the interval shrinks to empty without a match.

Takeaway

Binary search is an invariant game. Write down the interval you are preserving, then make every branch prove that the invariant still holds.

The same template powers #35 Search Insert Position, #74 Search a 2D Matrix, #153 Find Minimum in Rotated Sorted Array, and every "binary search on answer" problem later in the roadmap.

More in Binary Search Mastery