Introduction
Searching asks whether a key occurs in a collection and, if so, where. It is one of the most basic operations, and the choice of method depends on what is known about the data:
- Unsorted array. only linear search is possible, in the worst case.
- Sorted array with random access. binary search, in the worst case, which is optimal for comparison-based search.
- Dynamic sets. binary search trees search in , which can be in the worst case; balanced search trees guarantee search with fast updates; hash tables give expected search but no order.
This note treats linear and binary search, the boundary variants of binary search, and the lower bound that makes binary search optimal.
Prerequisites
- Asymptotic Notation: versus .
- Arrays: contiguous storage and constant-time indexing.
- Solving Recurrences: .
Linear search
Purpose. Find the first index with in an array that may be in any order. Input. Array , key . Output. An index with , or NIL.
Pseudocode uses 1-based arrays, <- for assignment and A[i..j] for the subarray from position to position .
LINEAR-SEARCH(A, n, x)
for i <- 1 to n
if A[i] = x then return i
return NIL| Case | Key comparisons | Time |
|---|---|---|
| Best () | 1 | |
| Worst ( absent or last) | ||
| Average, present, uniform position |
Space . Works on linked lists and on unsorted data, needs no preprocessing, and finds the first occurrence.
Variants.
- Sentinel search: store in so that the loop needs only one test per element (
while A[i] != x) instead of two (index bound and key). The count of key comparisons is unchanged in order; the constant improves. - Sorted input: linear search can stop as soon as , which can reduce unsuccessful-search work (an expectation requires an explicit query distribution) but leaves the worst case at .
Binary search
Purpose. Search a sorted array in logarithmic time by repeatedly halving the range that can contain . Preconditions. sorted in non-decreasing order, and constant-time access to any index (an array, not a linked list). Input. Sorted , key . Output. An index with , or NIL.
BINARY-SEARCH(A, n, x)
lo <- 1
hi <- n
while lo <= hi
mid <- floor((lo + hi) / 2)
if A[mid] = x then return mid
else if A[mid] < x then lo <- mid + 1
else hi <- mid - 1
return NILLoop invariant. If is in , it is in . Initially this is the whole array. Each comparison discards a part that cannot contain , because the array is sorted. When the range is empty, so is absent. Moreover, at that point is the position where would be inserted to keep sorted, and .
Implementation details that matter.
lo <- mid + 1andhi <- mid - 1guarantee progress. Writinglo <- midwithwhile lo < hican loop forever when .- In fixed-width integer languages such as C, compute
mid = lo + (hi - lo) / 2to avoid overflow oflo + hi. - The empty array () is handled: the loop does not run and NIL is returned.
Worked example
, .
Search for 61 (present).
| Probe | Action | ||||
|---|---|---|---|---|---|
| 1 | 1 | 11 | 6 | 34 | : |
| 2 | 7 | 11 | 9 | 61 | found, return 9 |
Search for 30 (absent).
| Probe | Action | ||||
|---|---|---|---|---|---|
| 1 | 1 | 11 | 6 | 34 | : |
| 2 | 1 | 5 | 3 | 15 | : |
| 3 | 4 | 5 | 4 | 21 | : |
| 4 | 5 | 5 | 5 | 27 | : |
| end | 6 | 5 | : return NIL; 30 belongs at position 6 |

Analysis
Each probe at least halves the live range: if it has elements, the next has at most . So the number of loop iterations is at most for . The recurrence gives by case 2 of the master theorem.
| Case | Probes (three-way comparisons) | Time |
|---|---|---|
| Best ( at the first ) | 1 | |
| Worst (successful or unsuccessful) | ||
| Average, successful, uniform over positions |
Space: iterative; stack if written recursively.
A probe here is one "three-way" comparison (less, equal or greater). If the code makes two two-way comparisons per probe (= then <), the comparison count can double; read the question's counting convention.
The comparison tree. The probes binary search can make form a binary tree: the root is the first , its left subtree handles and its right subtree . For this tree is perfect with levels. For , the 15 successful searches use probes in total, an average of , against a worst case of 4. In general, for the successful searches total probes, and every unsuccessful search takes exactly probes, because all failure leaves lie at depth .

Lower bound
Any algorithm that searches a sorted array only by comparing with elements needs three-way comparisons in the worst case. Its comparison tree must have a distinct node for each of the possible "found at " answers, and a binary tree of depth has at most nodes, so . Since , binary search is exactly optimal. Hashing beats this bound only because it does not work by comparisons.
Binary search variants
The plain version returns some matching index. With duplicates, the first or last occurrence, or a count, may be needed instead.
First occurrence (lower bound)
FIRST-OCCURRENCE(A, n, x) // smallest i with A[i] >= x, or n+1
lo <- 1
hi <- n + 1
while lo < hi
mid <- floor((lo + hi) / 2)
if A[mid] < x then lo <- mid + 1
else hi <- mid
return loThe invariant is (treating as ). The loop always terminates because , so hi <- mid shrinks the range. Then is present if and only if and .
Replacing < by <= in the test gives the smallest with (the upper bound). The number of occurrences of is (upper bound) minus (lower bound), found with two binary searches in time. For and : lower bound 2, upper bound 5, count 3.
Binary search on a monotone predicate
Binary search works on any predicate that is false for all below some threshold and true from it onwards: find the first true index in evaluations. Examples: the smallest with (integer square root), the first bad version in a sequence of builds, or the minimum capacity that lets a schedule finish in time.
Two standard problems reduce to this form.
- Fixed point. Given sorted distinct integers , find with . Distinct integers rise by at least 1 per step, so is non-decreasing and is monotone. Find the first true and test . For : probes at 4 (, go left), 2 (, go right), 3 (, go right), and the answer is . With duplicates allowed the predicate is no longer monotone and no bound holds in general.
- Maximum of a bitonic array (strictly increasing, then strictly decreasing). Use , which is false on the rising part and true from the peak on. For : probes at 4 (, go left), 2 (, go right), 3 (, go right); the peak is at index 4. Equal neighbours break the method, so check that the question says "strictly".
Searching without a known length
To search a sorted sequence of unknown length, require an infinite sequence or a safe accessor returning an out-of-range sentinel treated as . Probe index 1 first: if its value is at least , test that element (or report absence for the sentinel). Otherwise probe until the value is at least or the sentinel is reached, then binary search the integer interval with the same safe accessor, never treating the sentinel as a real match. For a present key at position , time is .
Related methods
Related material. These methods are not named in the GATE syllabus. They are included because they are commonly studied together with binary search.
- Ternary search splits into three parts with two comparisons per step: about comparisons, more than binary search's . Binary search is preferred for sorted-array membership because ternary search uses more comparisons. Ternary search also has a common application in unimodal-function optimization.
- Interpolation search guesses the position from the key's value. On keys drawn uniformly at random it averages probes, but its worst case is .
Important properties and observations
- Binary search needs both sorted order and random access. On a sorted linked list it still costs because reaching the middle takes linear time.
- Sorting first and then binary searching costs for searches; this beats linear searches only when is larger than about .
- Worst-case probes for : 1, 2, 2, 3, 3, 4, 4, 5. The count increases exactly when reaches a power of 2.
- The final value of in an unsuccessful search is the insertion position; this is how sorted insertion and "rank" queries are answered.
GATE examination perspective
- Traces. Follow , and row by row as in the worked example; common errors are rounding up instead of down, or mixing 0-based and 1-based indices.
- Counting. "maximum number of comparisons" is three-way probes; check whether two-way comparisons are counted instead.
- Correctness of code variants. look for
lo = midwithout a matchingwhile lo < hiand rounding rule (infinite loop), missing+ 1or- 1, and wrong loop conditions that skip the last element. - Disguised binary search. fixed point in sorted distinct integers, peak of a bitonic array, first true value of any monotone predicate: .
- Complexity traps. binary search on a linked list is ; counting occurrences in a sorted array is , not .
Summary
Sources
- T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein, Introduction to Algorithms, 3rd ed., MIT Press, 2009: Exercise 2.3-5 (binary search and its Θ(lg n) worst case) and Section 8.1 (decision-tree lower bounds).