skip to content

questions

5

Why does a standard binary search fail on a sorted array rotated by an unknown offset?

level: juniorimportance: must knowfreq 78%

answer

  1. what does binary search assume about order
  2. the discard rule needs a global guarantee
  3. rotation breaks the order in exactly one place
  4. cut anywhere: how much is still ordered
  5. check the ordered side's endpoints, not the midpoint

basics

~20 s

Standard binary search assumes a total ascending order, so one comparison against the midpoint tells it which side to discard. Rotation breaks that assumption, so the discard rule can throw away the very half that holds the target.

solid answer

~50 s

Binary search's discard rule rests on a global guarantee: everything left of the midpoint is smaller, everything right is larger. Rotating a sorted array by an unknown offset destroys that guarantee — there is one wrap point where a large value is immediately followed by the smallest one — so `target < a[mid]` no longer implies the target is on the left. What survives rotation is weaker but still enough: **cut the range at any midpoint and at least one of the two sides contains no wrap point, so that side is fully in order**. The repair is therefore two-step per iteration: first work out which side is in order by comparing the midpoint value to an endpoint value, then test the target against that side's two endpoints to decide whether to keep it or move to the other side. That keeps the search logarithmic when the values are distinct.

go deeper

for a junior

Recall the one-sentence reason: the discard rule assumes total order and rotation breaks it, so the wrong half can be thrown away and the search reports not-found. Then state the surviving property — at least one side of any split is in order.

for a middle

Explain the mechanism with a worked trace: pick a small rotated array, show a concrete target the naive rule loses, then show how the ordered-side test recovers it. Be precise that the failure is a wrong answer, not a crash.

for a senior

Show where this shape appears in real systems — wrapped capture buffers, ring-backed logs — and say when you would not bother: small ranges scan fine, and correctness risk in clever index code is a real cost you weigh.

for a principal

Own the framing question: should the data arrive rotated at all? Recording the wrap position at write time, or normalising once on read, removes the whole class of index bugs and is often the cheaper long-term call.

## What rotation actually does Take an array that was sorted ascending and rotate it by an unknown offset `k`: the element that used to sit at index `k` now sits at index `0`, and the elements that used to be in front of it wrap around to the end. Values `10 20 30 40 50` rotated by 3 become `40 50 10 20 30`. Nothing was reordered in the circular sense — read the array as a ring and it is still ascending — but read it linearly, which is how indexing works, there is exactly one place where the order breaks: between `50` and `10`. That single break is called the **wrap point** (equivalently, the pivot, or the position of the minimum). A concrete setting: a fixed-size capture buffer records monotonically increasing sequence numbers and overwrites the oldest slot when it fills. Dump its raw storage after a crash and you get exactly this shape — an ascending run, one drop, another ascending run — because the writer was part-way round the ring when it stopped. ## Why the classic discard rule needs more than "mostly sorted" Binary search does not need the array to be *nearly* sorted; it needs a specific implication to hold at every step: > if `target < a[mid]` then the target, if present, lies strictly left of `mid` That implication is licensed only by total order over the index range. In `40 50 10 20 30`, take `mid = 2` with `a[mid] = 10` and search for `40`. Since `40 > 10`, the classic rule discards indices `0..2` and searches `20 30`. The target was at index `0`. The algorithm does not loop forever or crash — it confidently reports *not found*, which is the dangerous failure mode: a silently wrong answer, not an exception. A related wrong instinct is "it is still sorted, just starting somewhere else, so binary search is fine". Circularly sorted is not the same as sorted, and binary search operates on indices, not on the ring. ## The property that does survive Pick any `lo <= mid <= hi`. The wrap point is a single position, so it lies in at most one of the two segments `lo..mid` and `mid..hi`. Therefore **at least one of those two segments is free of the wrap point and is genuinely in ascending order**. (When the offset is `0`, or when the range no longer straddles the wrap, both segments are in order — that is fine, the guarantee is "at least one".) This is what makes the problem tractable in logarithmic time. Each iteration becomes: 1. Determine which segment is in order — by comparing the midpoint value with an endpoint value, never with the target. 2. In that ordered segment, the classic range test applies: the target is inside it if it falls between the segment's two endpoint values. 3. If it does, continue inside the ordered segment; otherwise discard it and continue in the other one, which is where the wrap lives. Either branch halves the range, so with distinct values the cost stays O(log n) — the same bound as ordinary binary search, with a bigger constant because each step does two or three comparisons instead of one. ## Boundaries worth knowing early - **Offset zero is a legal rotation.** Whatever you write must still be correct on an array that was never rotated; several tempting shortcuts fail exactly there. - **The target's value tells you nothing about the offset.** You cannot deduce where the wrap is from the target alone; you deduce it from midpoint-versus-endpoint comparisons. - **Distinct values are doing real work in the O(log n) claim.** Once values repeat, a midpoint can tie with an endpoint and the ordered-side test stops discriminating, which pushes the worst case up to linear. The bound is O(log n) *for distinct values*. - **Sorting first is not a fix.** Sorting costs more than the linear scan you were trying to avoid, and it destroys the recency information the rotation encodes — in the capture-buffer case, the wrap point is precisely what tells you where the oldest record is. ## The honest fallback If you cannot reconstruct the ordered-side reasoning under interview pressure, say so and give the linear scan: it is O(n), obviously correct, and for a buffer of a few thousand entries perfectly adequate. What loses points is claiming the unmodified logarithmic search still works, because that is a correctness error, not a performance one.

  • After rotation, is there any comparison that still tells you something reliable?
    Yes — comparing the midpoint value against an endpoint value of the current range. That comparison reveals which of the two segments contains no wrap point and is therefore fully in order. Comparing the midpoint against the target is what stops being informative, because the target's relation to the midpoint no longer implies a side.
  • Does a rotation offset of zero need special handling?
    It should not. A zero offset leaves the array identical to the unrotated one, and the ordered-side test simply reports the whole range as in order, at which point the algorithm behaves like an ordinary binary search. Any solution that misbehaves on offset zero has a real bug — it is the most likely input in practice.
  • What is the cost of just scanning linearly instead?
    O(n) time, O(1) space, and it is trivially correct on any rotation and any duplicates. For small ranges it is often the right engineering answer; the logarithmic version earns its keep when the data is large or queried repeatedly. State the scan as your baseline, then improve on it.

A circular running track is uniformly numbered, but if you photograph it as a straight strip starting at an arbitrary gate, the numbers jump once. Directions like "smaller numbers are behind you" stop being reliable at that one seam.

saying these in an interview costs you the question

  • Says the array is still sorted, just starting elsewhere, so binary search works
  • Claims binary search only needs more iterations after rotation
  • Proposes sorting the array first and calls it O(log n)
  • Thinks the target's value reveals the rotation offset
  • Assumes rotation always moves the smallest element into the middle

context

open as a page

How do you decide which half of a rotated sorted array is in order at each step?

level: middleimportance: must knowfreq 70%

basics

~20 s

Compare the midpoint value against a range endpoint, never against the target. If the midpoint value is at most the value at the high end, the segment from midpoint to high is in order; otherwise the low-to-midpoint segment is.

open as a page

Why does a wrap-point search in a rotated array shrink with hi = mid, not hi = mid - 1?

level: middleimportance: should knowfreq 55%

basics

~20 s

The midpoint itself may be the wrap point: when its value is not greater than the value at the high end, it stays a candidate for the smallest element, so discarding it can lose the answer.

open as a page

How do duplicate values change the worst case of searching a rotated sorted array?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Duplicates can make the midpoint tie with both endpoints, leaving the ordered side unidentifiable. The only safe move is then to shrink one bound by a single position, so the worst case rises from O(log n) to O(n).

open as a page

When is a rotation-aware search not worth shipping, and what would you build instead?

level: principalimportance: nice to knowfreq 26%

basics

~20 s

A rotation-aware search is not worth shipping when the range is small, queried rarely, or written by code you control. Recording the wrap position at write time, or normalising once on read, removes the rotation and a class of boundary bugs.

open as a page