Binary Search
Binary search finds an item in a sorted array in O(log n). The trick is getting the bounds right: low = 0, high = n - 1 (or n for half-open), mid = low + (high - low) / 2 to avoid overflow.
Classic + variants + answer-search
EXAMPLE
// 1) Classic — find target index, return -1 if missing
function binarySearch(arr, target) {
let lo = 0, hi = arr.length - 1;
while (lo <= hi) {
const mid = lo + ((hi - lo) >> 1); // overflow-safe + integer
if (arr[mid] === target) return mid;
if (arr[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
// 2) Find the leftmost (first) occurrence — lower_bound
function lowerBound(arr, target) {
let lo = 0, hi = arr.length; // half-open
while (lo < hi) {
const mid = lo + ((hi - lo) >> 1);
if (arr[mid] < target) lo = mid + 1;
else hi = mid;
}
return lo; // index of first element >= target (could be arr.length)
}
// 3) Find the rightmost — upper_bound
function upperBound(arr, target) {
let lo = 0, hi = arr.length;
while (lo < hi) {
const mid = lo + ((hi - lo) >> 1);
if (arr[mid] <= target) lo = mid + 1;
else hi = mid;
}
return lo; // index of first element > target
}
// Count occurrences
const count = upperBound(arr, t) - lowerBound(arr, t);
// 4) Rotated sorted array — find target in [4,5,6,7,0,1,2]
function searchRotated(arr, target) {
let lo = 0, hi = arr.length - 1;
while (lo <= hi) {
const mid = lo + ((hi - lo) >> 1);
if (arr[mid] === target) return mid;
if (arr[lo] <= arr[mid]) { // left half sorted
if (target >= arr[lo] && target < arr[mid]) hi = mid - 1;
else lo = mid + 1;
} else { // right half sorted
if (target > arr[mid] && target <= arr[hi]) lo = mid + 1;
else hi = mid - 1;
}
}
return -1;
}
// 5) Find peak element (any local max)
function findPeak(arr) {
let lo = 0, hi = arr.length - 1;
while (lo < hi) {
const mid = lo + ((hi - lo) >> 1);
if (arr[mid] < arr[mid + 1]) lo = mid + 1;
else hi = mid;
}
return lo;
}
// 6) Search the ANSWER space — binary-search on a value, not an index
// Find the smallest capacity for shipping `weights` within D days
function shipCapacity(weights, D) {
let lo = Math.max(...weights);
let hi = weights.reduce((a, b) => a + b, 0);
while (lo < hi) {
const cap = lo + ((hi - lo) >> 1);
if (feasible(weights, D, cap)) hi = cap;
else lo = cap + 1;
}
return lo;
}
function feasible(weights, D, cap) {
let days = 1, load = 0;
for (const w of weights) {
if (load + w > cap) { days++; load = 0; }
load += w;
}
return days <= D;
}
// 7) Search in 2D matrix (row + col sorted)
function search2D(m, target) {
let r = 0, c = m[0].length - 1;
while (r < m.length && c >= 0) {
if (m[r][c] === target) return [r, c];
if (m[r][c] > target) c--;
else r++;
}
return null;
}
// 8) Python — bisect module
# import bisect
# i = bisect.bisect_left(arr, target) # lower_bound
# i = bisect.bisect_right(arr, target) # upper_bound
# bisect.insort(arr, x) # insert keeping sorted
// 9) Common bugs
// • mid = (lo + hi) / 2 → overflow on int_max sized arrays. Use lo + (hi - lo) / 2.
// • Off-by-one: <= vs < bounds. Decide closed [lo, hi] or half-open [lo, hi) — stick with it.
// • Infinite loop when lo doesn't progress — ensure each branch shrinks the range.
// • Floating-point binary search — use a fixed iteration count, not termination by equality.
// 10) When binary search is the right tool
// • Sorted data (obviously)
// • You can express a monotonic predicate on the index/value
// • You're searching the ANSWER space (min cost, min capacity, max value satisfying X)
// • You can transform an O(n) check into a yes/no question
Why it matters
Most “binary search on the answer” problems look like sorting/scheduling at first glance. The trick: ask “can I do it with capacity X?” — if yes/no is monotonic, binary-search on X instead of brute force.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
function search(nums, target) {
let lo = 0, hi = nums.length - 1;
while (lo <= hi) {
const m = (lo + hi) >> 1;
if (nums[m] === target) return m;
if (nums[m] < target) lo = m + 1; else hi = m - 1;
}
return -1;
}
Try it Yourself »
Exercise
Loop condition for classic binary search.
while (lo
hi) { /* … */ }
Two characters.
Discussion
Loading…