Linear and binary search
Finding a key in a collection: linear search and its best, worst and average cost, binary search on a sorted array with its invariant, the exact worst case floor(log2 n) + 1, why this is optimal, the midpoint overflow, the first-occurrence variant, and why binary search needs both order and random access.
Why it exists
Almost every program needs to find things: a record by its key, a word in a dictionary, a value in a table. How fast this can be done depends on what is known about the collection. If nothing is known, every element may have to be looked at. If the elements are sorted and can be reached by position, each look can throw away half of what remains, and a million elements need only 20 looks. This page shows both ends, and the reason the second needs two assumptions (order and direct access), which is what exam questions test.
Prerequisites
You need to count the steps of a loop (analysing loops) and to know that an array gives direct access to any position (arrays).
Precise definitions
Search problem. Given a collection and a key , report a position with , or report that there is none. A search is successful if the key is present and unsuccessful otherwise.
Linear (sequential) search. Examine in order until the key is found or the end is reached. It needs no assumption about the collection and works on arrays and on linked lists.
Binary search. For an array sorted in increasing order, keep a range that contains every position where the key could still be. Examine the middle element ; if it equals the key, stop; if it is smaller than the key, the key can only be to the right, so set ; otherwise set . Stop when the range is empty.
Invariant. If the key is in the array at all, its position is in . It is true at the start (, ), each step keeps it true (because the array is sorted), and when the loop ends with the range is empty, so the key is absent. The range at least halves each time, which is why the loop ends.
Probe. One examination of an array element. Binary search makes one probe per iteration. The C code below uses two tests per probe (== and <), but they are one three-way comparison of the key with (less, equal, greater). Exam questions count either probes or three-way comparisons, which are the same number; if a question counts every == and < separately it will say so.
Costs. For linear search the best case is probe, the worst case is , and for a successful search with the key equally likely at each position the average is . For binary search the best case is and the worst case is probes (equivalently ).
How it works
Both searches in C. They are the code that produced the numbers below; probes counts the array elements examined.
#include <stdio.h>
/* both return the index of key or -1; *probes receives the number of array elements examined */
static int linear_search(const int a[], int n, int key, int *probes) {
*probes = 0;
for (int i = 0; i < n; i++) {
(*probes)++;
if (a[i] == key) return i;
}
return -1;
}
static int binary_search(const int a[], int n, int key, int *probes) {
int lo = 0, hi = n - 1;
*probes = 0;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
(*probes)++;
if (a[mid] == key) return mid;
if (a[mid] < key) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
int main(void) {
int sizes[] = {1, 3, 7, 8, 15, 16, 100, 1000};
static int a[1000];
printf("%5s %9s %9s %7s %9s %7s %6s\n", "n", "lin-hit", "bin-hit", "bin-max", "bin-miss", "miss-max", "bound");
for (int s = 0; s < 8; s++) {
int n = sizes[s], p;
long lin_hit = 0, bin_hit = 0, bin_miss = 0;
int hit_max = 0, miss_max = 0;
for (int i = 0; i < n; i++) a[i] = 2 * i; /* the keys are 0, 2, 4, ... */
for (int i = 0; i < n; i++) { /* every successful search, once */
linear_search(a, n, 2 * i, &p);
lin_hit += p;
binary_search(a, n, 2 * i, &p);
bin_hit += p;
if (p > hit_max) hit_max = p;
}
for (int g = 0; g <= n; g++) { /* every unsuccessful search: -1, 1, 3, ..., 2n - 1 */
binary_search(a, n, 2 * g - 1, &p);
bin_miss += p;
if (p > miss_max) miss_max = p;
}
int bound = 0;
for (int m = n; m > 0; m /= 2) bound++; /* floor(log2 n) + 1 */
printf("%5d %9ld %9ld %7d %9ld %7d %6d\n", n, lin_hit, bin_hit, hit_max, bin_miss, miss_max, bound);
}
return 0;
} n lin-hit bin-hit bin-max bin-miss miss-max bound
1 1 1 1 2 1 1
3 6 5 2 8 2 2
7 28 17 3 24 3 3
8 36 21 4 29 4 4
15 120 49 4 64 4 4
16 136 54 5 70 5 5
100 5050 580 7 680 7 7
1000 500500 8987 10 9987 10 10Read the columns for each (the keys are , so every odd number is an unsuccessful search):
lin-hitis the total number of probes of linear search over all successful searches: , so the average is . An unsuccessful linear search always examines all elements.bin-hitandbin-missare the totals of binary search over all successful and all unsuccessful searches. For a successful search takes probes on average.bin-maxandmiss-maxare the worst cases, andboundis . They agree in every row, for present and for absent keys.
Probes of linear and binary search, measured: start
Computed by a script, not typed| n | linear: average probes (hit) | linear: probes (miss) | binary: average probes (hit) | binary: worst probes (hit) | binary: worst probes (miss) | floor(log2 n) + 1 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 3 | ||||||
| 7 | ||||||
| 8 | ||||||
| 15 | ||||||
| 16 | ||||||
| 100 | ||||||
| 1000 |
Step 0
Every successful search (each key once) and every unsuccessful search (each gap once) was run on sorted arrays of n keys, counting the array elements examined. The numbers come from the C program on this page.
The animation. The code is binary_search from the page, run for real: faded positions are ruled out. The first search finds 47 in four probes (positions 7, 11, 9, 10); the second search, for 30, ends when passes after four probes.
Binary search: halve the range of possible positions
Real runC source
Sorted array a
State
Blue = the position this step is working on, amber = a position being compared, red = positions just swapped, green = finished or in its final place, a filled blue cell = a value just placed, faded = not part of the structure at this step.
Step 1
A sorted array of 15 keys. First search for 47, then for 30.
Why . After probes at most positions remain (rounded down), so the range is empty after at most probes. More exactly, a range of size becomes a range of size at most , and only after the size has been halved times. The recurrence of the running time is , which gives (Master theorem, case 2).
Binary search is optimal. Any algorithm that searches a sorted array by comparing the key with elements must be able to answer "present at position " for each of the positions, and it can only do so after it has compared the key with . So its decision tree has at least internal nodes, one per key, and each node has at most two continuing branches (less and greater). A binary tree with nodes has a path of at least nodes, so some search needs that many comparisons, which is exactly the worst case of binary search.
Why the loop condition and the updates matter. The updates must be lo = mid + 1 and hi = mid - 1, because has just been examined and excluded. An update lo = mid can loop forever: with and the middle is and nothing changes.
The midpoint. The expression (lo + hi) / 2 adds two valid indices; if their sum exceeds the largest int the addition overflows (undefined behaviour for signed integers in C). The expression lo + (hi - lo) / 2 never leaves the range between and . The program below uses 64-bit arithmetic to show the true numbers without invoking undefined behaviour.
#include <stdio.h>
#include <limits.h>
int main(void) {
long long lo = 1500000000, hi = 1600000000; /* two valid indices of a huge array */
printf("INT_MAX = %d\n", INT_MAX);
printf("lo + hi = %lld\n", lo + hi);
printf("fits in an int = %s\n", lo + hi <= INT_MAX ? "yes" : "no");
printf("lo + (hi - lo)/2 = %lld\n", lo + (hi - lo) / 2);
return 0;
}INT_MAX = 2147483647
lo + hi = 3100000000
fits in an int = no
lo + (hi - lo)/2 = 1550000000First occurrence. With duplicates, plain binary search returns some matching position. To find the first one (the lower bound, the first position whose element is not smaller than the key) keep the half-open range and never stop early:
/* a[0..n-1] is sorted; returns the first position whose element is not smaller than key (n if there is none) */
int lower_bound(const int a[], int n, int key) {
int lo = 0, hi = n;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] < key) {
lo = mid + 1;
} else {
hi = mid;
}
}
return lo;
}The result is the first position of the key if it is present, and otherwise the position where the key would have to be inserted to keep the array sorted. For the 15-key array of the animation, lower_bound of 30 is , which is where stands.
What binary search needs. Two things at once. Order: without it, discarding half is wrong. Direct access: finding the middle element must cost . On a sorted linked list reaching the middle costs steps, then , and so on, in total : binary search on a linked list is no better than linear search. On a sorted array with many insertions, keeping the order costs shifts per insertion, which is why other structures (balanced search trees, hash tables) are used for dynamic sets.
Outside the syllabus. If the keys are spread evenly, interpolation search guesses the position from the key's value and takes expected probes, but its worst case is .
Worked examples
EX 1Trace a binary search
EasyArray (positions 0 to 14), key . Probe position (31): too small, . Probe (55): too big, . Probe (42): too small, . Probe (47): found. Four probes, matching the animation. A linear search would have needed .
EX 2The worst-case count for a given n
EasyThe worst case is . For : , so . For : , so . For the answer is (the binary tree of probes is perfectly full); for it is , one more. In the table above gives and gives .
EX 3An unsuccessful search and the insertion point
MediumSearch for in the same array. Probe (31): too big, . Probe (12): too small, . Probe (23): too small, . Probe (27): too small, . Now : stop, absent, after four probes. The final is the position at which would be inserted, the same value lower_bound returns.
EX 4Average cost of binary search
MediumFor the probes form a perfectly full tree with nodes at depth , so a successful search takes probes for of the keys. The total over all keys is . For () this is , which is the bin-hit value in the table, and for it is , also in the table. The average is : about one probe fewer than the worst case.
EX 5Binary search on a linked list, and on unsorted data
GATE level(a) A sorted singly linked list of nodes is searched with the binary search idea: to examine the middle of a range of nodes we walk steps, so the total work is steps, although only comparisons are made. The time is , not . (b) Binary search on an array that is not sorted is not slower, it is wrong: for and the key the first probe (position 2, value 4) says "too big", the left half is kept, and the key is missed. (c) A sorted array of keys is searched times: with binary search the time is ; with linear search . If is small (say ) sorting first, at , costs more than one linear search.
Cheat box
Cheat box
- Linear search: best , worst , average successful , unsuccessful . Works on any collection, array or list.
- Binary search: sorted array with direct access. Invariant: if the key is present it is in . Worst case probes; best case ; time ; .
- : worst case . : worst case .
- Updates are
lo = mid + 1andhi = mid - 1. Midpoint:lo + (hi - lo) / 2. - Binary search is optimal among comparison-based searches of a sorted array.
- On a linked list the comparisons are but the time is .
- Iterative binary search uses space; the recursive version uses stack.
Traps and GATE patterns
Connections
Across subjects
Binary search is the simplest divide and conquer algorithm: one subproblem of half the size and constant work, see divide and conquer; its recurrence is solved in solving recurrences. A binary search tree makes the same decisions with pointers instead of indices (binary search trees), and a hash table trades order for expected constant time.
PYQs
7 previous year questions from your book. I re-solved each one myself (5 by running or simulating, 2 by reasoning only); the book's key is shown next to my answer. All PYQs
Consider the following array: 23 , 32 , 45 , 69 , 72 , 73 , 89 , 97 Which algorithm out of the following options uses the least number of comparisons (among the array elements) to sort the above array in ascending order?
- (a)Quicksort using the last element as pivot
- (b)Selection sort
- (c)Merge sort
- (d)Insertion sort
Given an integer array of size N, we want to check if the array is sorted (in either ascending or descending order). An algorithm solves this problem by making a single pass through the array and comparing each element of the array only with its adjacent elements. The worst-case time complexity of this algorithm is
- (a)Both O(n)and Ω (n)
- (b)O(n) but not Ω (n)
- (c)Ω (n) but not O(n)
- (d)Neither O(n) nor Ω (n) v Check Out Our Gate Courses & Secure Your Dream Rank !
What is the worst-case number of arithmetic operations performed by recursive binary search on a sorted array of size n
- (a)O(n)
- (b)O(n2)
- (c)O(√n )
- (d)O(log2n)]
Let A be an array of 31 numbers consisting of sequence of 0's followed by a sequence of 1's. The problem is to find the smallest index i that A[i] is 1 by probing the minimum numbers of locations in A. The worst case number of probes performed by an optimal algorithm is .
Match the algorithms with their time complexities: Algorithm Time complexity P Towers of Hanoi with n disks i Θ(n2 ) Q Binary search given n sorted numbers ii Θ(nlog n) R Heap sort given n numbers at the worst case iii Θ(2n ) S Addition of two n × n matrices iv Θ(logn) ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank !
- (a)P-(iii), Q-(iv), R-(i), S-(ii)
- (b)P-(iv), Q-(iii), R-(i), S-(ii)
- (c)P-(iii), Q-(iv), R-(ii), S-(i)
- (d)P-(iv), Q-(iii), R-(ii), S-(i)
An unordered list contains n distinct elements. The number of comparisons to find an element in this list that is neither maximum nor minimum is :
- (a)O(nlogn)
- (b)O(n)
- (c)O(logn)
- (d)O(1)
Consider the C function given below. Assume that
the array listA contains n(>0) elements, sorted in
ascending order
int ProcessArray(int *listA, int x, int n)
{
int i, j, k;
i = 0;
j = n-1;
do {
k = (i+j)/2;
if (x <= listA[k]) j = k-1;
if (listA[k] <= x) i = k+1;
}
while (i <= j);
if (listA[k] == x) return(k);
else return -1;
}
Which one of the following statements about the
function ProcessArray is CORRECT?- (a)It will run into an infinite loop when x is not in listA.
- (b)It is an implementation of binary search.
- (c)It will always find the maximum element in listA.
- (d)It will return -11 even when xx is present in listA.
Self-check
Question 1
How many array elements does binary search examine, at most, in a sorted array of elements?
Show answerHide
.
Question 2
What is the average number of comparisons of a successful linear search in an array of elements if every position is equally likely?
Show answerHide
.
Question 3
Why does binary search on a sorted linked list not run in time?
Show answerHide
Reaching the middle node takes a number of steps proportional to the length of the range, so the steps add up to . Only the number of comparisons is .
Question 4
An array of sorted keys is searched for a key smaller than all of them. How many probes are needed?
Show answerHide
Four: the probes go to positions , and then the range is empty. (, so every search needs at most .)
Revision card
One-screen revision
- Linear search: / / probes (best / average successful / worst). Any collection.
- Binary search: sorted array, direct access, invariant "key in ", worst case probes, , , optimal.
lo = mid + 1,hi = mid - 1,mid = lo + (hi - lo) / 2.- Linked list: comparisons but time . Unsorted: wrong.
- Lower bound variant returns the first position not smaller than the key.
References
- ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (3rd edition), Chapter 2 Getting Started (2.1 and 2.3, the exercises on linear and binary search)
- ·Sedgewick and Wayne, Algorithms (4th edition), Section 1.1 (binary search)
- ·Knuth, The Art of Computer Programming, Volume 3, Section 6.2.1 Searching an ordered table
Verification
The C program on this page was compiled and run; its totals were recomputed by an independent Python implementation, and for every n up to 300 the worst case of binary search was confirmed to be floor(log2 n) + 1 probes for both present and absent keys, with the totals (k - 1) 2^k + 1 for n = 2^k - 1. The first-occurrence variant was compared with bisect_left on 3000 random arrays with duplicates. The animation is a real run of the C code shown (scripts/gen-algo-panel-traces.ts). Textbook chapter references are from memory. The remark on interpolation search is outside the GATE syllabus and is stated from general knowledge. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (loop counts, recurrences, merge and quicksort counts and averages, hash probes and load-factor formulas, DP tables, MST and shortest-path runs, Floyd matrices); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.
last verified: never
My notes (saved in this browser)