∑GATE DA Atlas

Searching — Linear Search and Binary Search

Linear search and its comparison counts, binary search (iterative and recursive) with its invariant and exact worst-case comparison count, variants for first/last occurrence and insertion points, Python's bisect module, binary search on the answer, common off-by-one bugs, and when sorting first pays off.

Section 49 practice questions

Scan elements one by one until the key is found.

Python
def linear_search(a, x):
    for i, v in enumerate(a):
        if v == x:
            return i
    return -1
CaseComparisons
Best (first element)1
Worst / unsuccessfulnn
Average, successful, uniform positionn+12\frac{n+1}{2}

O(n)O(n), works on unsorted data and on any sequential structure (linked lists, streams). For a key present with probability pp at a uniform position: expected comparisons pn+12+(1−p)np\frac{n+1}{2} + (1-p)n.

Sentinel trick: append the key at the end so the loop needs no bounds check (halves comparisons in low-level code).

On a sorted array, compare the key with the middle element and discard the half that cannot contain it.

Python
def binary_search(a, x):
    lo, hi = 0, len(a) - 1
    while lo <= hi:                 # invariant: if x is in a, it is in a[lo..hi]
        mid = (lo + hi) // 2
        if a[mid] == x:
            return mid
        elif a[mid] < x:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1                       # lo is now the insertion point
Python
def binary_search_rec(a, x, lo, hi):
    if lo > hi:
        return -1
    mid = (lo + hi) // 2
    if a[mid] == x:
        return mid
    if a[mid] < x:
        return binary_search_rec(a, x, mid + 1, hi)
    return binary_search_rec(a, x, lo, mid - 1)
16 lo = 0hi = 9mid = 4: 16 < 23 → go right 56 mid = 7: 56 > 23 → go left 23 mid = 5: found
Searching for 23 in [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]: three probes.

Cost

T(n)=T(n/2)+O(1)=O(log⁡n)T(n) = T(n/2) + O(1) = O(\log n). Worst-case number of three-way comparisons: ⌊log⁡2n⌋+1\lfloor\log_2 n\rfloor + 1 (10 for n=1000n = 1000, 20 for n=106n = 10^6). The comparisons trace a path in a balanced binary decision tree of height ⌊log⁡2n⌋\lfloor\log_2 n\rfloor.

Variants

GoalIdea
First occurrence (lower bound)on equality, record and continue left (hi = mid - 1)
Last occurrence (upper bound)on equality, continue right
Count of xupper_bound − lower_bound
Insertion pointthe final lo
Rotated sorted arrayone half is always sorted; check which and whether x lies in it
Peak elementmove towards the larger neighbour

Python's bisect module: bisect_left(a, x) (first index with a[i] >= x), bisect_right(a, x) (first index with a[i] > x), insort(a, x) (insert in order; O(n)O(n) because of shifting).

Binary search on the answer

If a predicate P(v)P(v) is monotone (false … false, true … true), binary search finds the boundary in O(log⁡(range))O(\log(\text{range})) evaluations: integer square roots, minimum capacity to ship packages in DD days, smallest threshold achieving a target, root-finding by bisection on a continuous function.

Sort first, or search repeatedly?

One search: linear search, O(n)O(n). Many searches (kk of them): sort once in O(nlog⁡n)O(n\log n), then O(log⁡n)O(\log n) each, total O((n+k)log⁡n)O((n + k)\log n) — or build a hash set for O(1)O(1) expected lookups if you only need membership (see hash tables).

MethodPreprocessingPer queryNeeds
Linear search—O(n)O(n)nothing
Binary searchsort O(nlog⁡n)O(n\log n)O(log⁡n)O(\log n)order, random access
Hash setO(n)O(n)O(1)O(1) expectedhashable keys; no order
Balanced BSTO(nlog⁡n)O(n\log n)O(log⁡n)O(\log n)order; supports updates

Quick revision

Practice questions

GATE-style questions: 2 one-mark and 7 two-mark. Wrong MCQs cost ⅓ of their marks in the real exam; MSQ and NAT have no negative marking. Attempt each before opening the solution.

Q1NAT1 mark

The maximum number of element comparisons (three-way: less / equal / greater) made by binary search on a sorted array of 1000 elements is ______.

Q2NAT2 marks

Linear search is applied to an array of 9 distinct elements, and the key is present at a uniformly random position. The expected number of comparisons is ______.

Q3MCQ2 marks

What does this program print?

Python
def bs(a, x):
    lo, hi = 0, len(a) - 1
    mids = []
    while lo <= hi:
        mid = (lo + hi) // 2
        mids.append(a[mid])
        if a[mid] == x:
            return mids
        if a[mid] < x:
            lo = mid + 1
        else:
            hi = mid - 1
    return mids

print(bs([2, 5, 8, 12, 16, 23, 38, 56, 72, 91], 23))
Q4MSQ2 marks

For binary search to run in O(log⁡n)O(\log n) time, which conditions are required?

One or more options are correct.

Q5NAT2 marks

What does this program print?

Python
from bisect import bisect_left, bisect_right
a = [1, 2, 2, 2, 3, 5]
print(bisect_right(a, 2) - bisect_left(a, 2))
Q6MCQ1 mark

The worst-case time complexity of binary search on a sorted array of nn elements is

Q7NAT2 marks

Binary search (three-way comparisons) is run on a sorted array of 64 elements. The maximum number of comparisons in an unsuccessful search is ______.

Q8MCQ2 marks

In the loop while lo <= hi: with mid = (lo + hi) // 2, which change can make binary search loop forever?

Q9NAT2 marks

What does this program print?

Python
def isqrt(n):
    lo, hi = 0, n
    while lo < hi:
        mid = (lo + hi + 1) // 2
        if mid * mid <= n:
            lo = mid
        else:
            hi = mid - 1
    return lo

print(isqrt(50))