3.6.11 · D3Sorting & Searching

Worked examples — Binary search — iterative, recursive; O(log n); searching in sorted - rotated arrays

4,610 words21 min readBack to topic

Before we start, one reminder of the three moving parts (all defined in the parent):

  • lo — the left edge of the window we still trust to maybe hold the target.
  • hi — the right edge of that window.
  • mid — the element half-way between them, computed as mid = lo + (hi - lo) // 2.
  • n — the length (number of elements) of the array. Indices run from 0 to n - 1, so the very first window is lo = 0, hi = n - 1.

The window [lo, hi] is the promise "if the target exists, it is somewhere in here." Every step shrinks it.

Both blocks below run this exact loop — keep it in view; every worked step is just one turn of it:

def bsearch(arr, target):
    lo, hi = 0, len(arr) - 1        # n = len(arr); window is [0, n-1]
    while lo <= hi:                 # guard: window still has >= 1 element
        mid = lo + (hi - lo) // 2   # overflow-safe midpoint (see note above)
        if arr[mid] == target:
            return mid              # hit
        elif arr[mid] < target:
            lo = mid + 1            # discard mid and everything left of it
        else:
            hi = mid - 1            # discard mid and everything right of it
    return -1                       # window emptied -> not present

And the rotated variant (used in Ex 6–9), which first names the sorted half:

def search_rotated(arr, target):
    lo, hi = 0, len(arr) - 1
    while lo <= hi:
        mid = lo + (hi - lo) // 2
        if arr[mid] == target:
            return mid
        if arr[lo] <= arr[mid]:                 # LEFT half is sorted
            if arr[lo] <= target < arr[mid]:    # target lies inside it
                hi = mid - 1
            else:
                lo = mid + 1
        else:                                   # RIGHT half is sorted
            if arr[mid] < target <= arr[hi]:    # target lies inside it
                lo = mid + 1
            else:
                hi = mid - 1
    return -1

The scenario matrix

Every binary-search problem you will ever be handed falls into exactly one of these cells. The job of this page is to leave no cell un-worked.

# Cell (what makes it special) Array kind Worked in
C1 Target sits in the middle — found on step 1 plain sorted Ex 1
C2 Target at the first index (left boundary) plain sorted Ex 2
C3 Target at the last index (right boundary) plain sorted Ex 2
C4 Target absent, between two values → -1 plain sorted Ex 3
C5 Target smaller than everything / larger than everything (out of range) plain sorted Ex 3
C6 Degenerate: empty array, single element plain sorted Ex 4
C7 Duplicates — which index do we get? plain sorted Ex 5
C8 Rotated, target in the un-sorted half rotated Ex 6
C9 Rotated, target in the sorted half rotated Ex 6
C10 Rotated, zero rotation (array not actually turned) rotated Ex 7
C11 Real-world word problem (mapping a story to indices) plain sorted Ex 8
C12 Exam twist — count steps / find the pivot rotated Ex 9

We will hit all twelve in nine examples.

The figure below is our map of the scenario matrix. It draws the workhorse array as ten cyan-outlined boxes on the blueprint grid, each labelled with its value on top and its index [0]..[9] underneath. Three amber arrows point down onto boxes — these are the cells where the search lands on a real element: the left one labelled "first index (C2)" hits box [0] (value 2), the centre one "middle hit (C1)" hits box [4] (value 16), the right one "last index (C3)" hits box [9] (value 91). Three cyan arrows point at empty space — these are the misses: one rises from the seam between boxes [4] and [5] labelled "gap = miss (C4) 20?" (there is no box there, so 20 falls through), one sits left of box [0] labelled "< all (C5) 1?", and one sits right of box [9] labelled "> all (C5) 100?". The lesson the picture teaches at a glance: amber = a box to land on, cyan = no box exists, which is exactly why those searches run the window off an end.

Figure — Binary search — iterative, recursive; O(log n); searching in sorted - rotated arrays

Plain sorted array examples

We use one workhorse array for the first block:

Here , indices 0..9. Since , the worst case is comparisons.


Rotated array examples

Recall from the parent: a rotated sorted array is a sorted array cut at one point and its front moved to the back, e.g. [4,5,6,7,0,1,2]. It is not globally sorted, but at least one side of mid is always sorted — the fact we derived above.

The figure below shows exactly how the rotated test reads. It draws rot = [15,18,2,3,6,8,11] as seven boxes with indices [0]..[6] underneath. The two amber-outlined boxes on the left (15, 18) are the "wrapped-high" front — the piece that used to be at the end and got moved forward. The five cyan-outlined boxes (2,3,6,8,11) are the sorted tail. A white arrow drops onto box [3] labelled "mid = 3, arr[mid]=3". Underneath the boxes are two coloured spans: an amber line under [0..3] labelled "left half: NOT sorted (pivot 18→2 inside)" — it crosses the cliff, so it is not sorted — and a cyan line under [3..6] labelled "right half: SORTED 3 < 6 < 8 < 11". Across the top, a white caption states the exact decision the code makes: "arr[lo]=15 > arr[mid]=3 ⇒ right side is the clean one." Read the picture as: whenever the left edge value exceeds the mid value, the cliff hides on the left, so trust the right span.

Figure — Binary search — iterative, recursive; O(log n); searching in sorted - rotated arrays

We use (indices 0..6, original sorted order rotated so that 15, 18 moved to the front).


Case coverage checklist

Recall Did we really hit every cell?

Middle hit ::: Ex 1 (C1) First / last index ::: Ex 2 (C2, C3) Absent between two values ::: Ex 3 (C4) Out of range both sides ::: Ex 3 (C5) Empty and single-element ::: Ex 4 (C6) Duplicates ::: Ex 5 (C7) Rotated, unsorted half ::: Ex 6 (C8) Rotated, sorted half ::: Ex 6 & 7 (C9) Rotated by zero ::: Ex 7 (C10) Word problem ::: Ex 8 (C11) Exam twist (find pivot) ::: Ex 9 (C12)


See also

  • Parent topic
  • Why halving is : Logarithms, Recurrence Relations, Time Complexity & Big-O
  • The slower baseline: Linear Search
  • Boundary variants (first/last occurrence): Lower & Upper Bound (bisect)
  • Order-as-structure instead of order-in-array: Binary Search Tree
  • Getting data sorted first: Sorting Algorithms