← SciSim / Computer Science

[~] Interpolation Search

Improved Binary Search | Distribution-Sensitive | O(log log n) avg

Standard Undergraduate

Section 1 -- Interactive Simulation

Speed:
0
Operations
0
Comparisons
0/0
Step
16
n
n: 16     
INTERPOLATION-SEARCH(A, target):
  lo = 0, hi = n-1
  while lo <= hi and target >= A[lo] and target <= A[hi]:
    pos = lo + (target-A[lo])*(hi-lo) / (A[hi]-A[lo])
    if A[pos] == target: return pos
    elif A[pos] < target: lo = pos+1
    else: hi = pos-1
  return -1

Section 2 -- The Idea, Step by Step

Looking up "Zebra" in a paper dictionary, you don't open to the exact middle -- you flip almost to the back, because you already know Z lives near the end. Interpolation search teaches a computer that same trick: use the value you are hunting to guess where it probably sits, instead of blindly splitting the list in half.

A plain binary search always probes the midpoint. Interpolation search instead asks: if the values climb smoothly from the smallest $A[lo]$ up to the largest $A[hi]$, what fraction of the way up is my target? That fraction, times the width of the live window, points to the next probe:

$pos = lo + \dfrac{(target - A[lo])\,(hi - lo)}{A[hi] - A[lo]}$

Worked number: suppose a window holds the values $0$ to $1000$ spread evenly across indices $0$ to $100$, and we want $800$. The fraction is $800/1000 = 0.8$, so $pos = 0 + 0.8 \times 100 = 80$ -- a single jump straight to index $80$, where binary search's first guess would have been the midpoint $50$.

Why is this so fast? On uniformly spaced data each good probe does not just halve the window -- it shrinks it by a square-root factor, leaving about $\sqrt{n}$ candidates. After $k$ probes roughly $n^{1/2^k}$ elements remain; once that reaches a small constant, $2^k \approx \log_2 n$, so $k \approx \log_2 \log_2 n$. That is the celebrated $O(\log\log n)$: for a billion uniformly distributed integers, about $5$ probes versus binary search's $\sim 30$. The catch is the assumption of even spacing -- if the values are clustered or grow exponentially, the straight-line estimate misses badly and the cost can degrade all the way to $O(n)$, no better than scanning one by one.

Try this with the controls above: (1) Open the preset menu and choose Sorted so the values become evenly spaced ($5, 10, 15, \ldots$) -- the best case, where the formula's straight-line guess is almost exact. (2) Type a clustered list such as 1,2,3,4,5,500 into the custom box and press Apply: a single huge value warps the spacing, the exact situation where interpolation search misfires. (3) Drag the $n$ slider higher and picture the probe count -- binary search needs about $\log_2 n$ steps, while interpolation needs only about $\log_2 \log_2 n$ when the data is evenly spaced, so it barely grows at all.

Section 3 -- Complexity Analysis

SymbolMeaning
nInput size
T(n)Time complexity function
hHeight or depth of structure
kKey or rank parameter
W(n)Worst-case complexity
A(n)Average-case complexity
Step 1 -- Interpolation Formula. pos = lo + (target - A[lo]) x (hi-lo) / (A[hi]-A[lo]). Estimates target position assuming uniform distribution. Like looking up a word in a phone book by first letter rather than always opening to the exact middle.
Step 2 -- Average Case (uniform distribution). Each probe reduces remaining elements by sqrt factor. After k probes: ~n^(1/2^k) remain. Setting n^(1/2^k) to a small constant (~2) gives 2^k ~ log2 n, so k ~ log2 log2 n. T(n) = O(log log n) expected for uniform data.
Step 3 -- Worst Case. Adversarial or exponential distribution: probe near one end each time, reducing by 1 element. Worst case O(n), same as linear search.
Step 4 -- vs Binary Search. Binary Search: always O(log n). Interpolation: O(log log n) uniform, O(n) worst. For n=10^9 uniform integers: Binary ~30 probes, Interpolation ~5 probes.
Step 5 -- Guard condition. Must check A[hi] != A[lo] before computing pos to avoid division by zero. Also verify target is in range [A[lo], A[hi]] to avoid out-of-bounds index.
Step 6 -- When to use. Large sorted arrays with uniformly distributed integer values. Poor for strings, skewed distributions, or small arrays where constant factors dominate.

Section 4 -- FAQ

Why does it fail for non-uniform data? concept+
The formula assumes equal spacing. Clustered values cause wildly wrong position estimates -- potentially probing far from target every time. Binary Search is safer for unknown distributions.
What if A[hi] == A[lo]? concept+
Division by zero! Guard: if A[hi]==A[lo], check if target==A[lo] and return accordingly. This is a very common bug in implementations.
When exactly is it O(log log n)? complex+
Only for uniform distribution. The key is that each probe reduces the search space by a square-root factor in expectation. Phone books, uniformly random integers, and sequential IDs are good candidates.
How does it relate to Fibonacci Search? nonobv+
Fibonacci Search uses Fibonacci-number splits (no division) -- useful when division is expensive. Interpolation uses value-based estimation. Neither dominates; choice depends on data distribution and hardware constraints.
Does it work for duplicates? applied+
Yes, but after finding a match, finding first or last occurrence requires linear scan. The formula can probe into the middle of a run of equal values.
Why is O(log log n) so dramatic? deep+
log(log(10^9)) ~= 5 probes. For a trillion-element uniform array: only 6 comparisons. In practice cache misses dominate since the predicted position is rarely in CPU cache -- each probe may be a cache miss.

Section 5 -- Common Misconceptions

Conceptual Misconceptions

X Interpolation Search is always faster than Binary Search.

O Only for large, uniformly distributed numeric data. For strings, skewed data, or small arrays, Binary Search wins.

X O(log log n) is the guaranteed time complexity.

O Only expected time for uniform distribution. Worst case is O(n).

X It works directly on any data type.

O Formula requires arithmetic on values. Strings need lexicographic comparison. Only use for numeric keys.

Implementation Errors

X Forgetting to check A[hi]==A[lo] before computing pos.

O Division by zero if A[hi]==A[lo]. Always guard: if A[hi]==A[lo]: check target==A[lo].

X Using int arithmetic -- overflow risk.

O Use 64-bit: (long)(target-A[lo])*(hi-lo)/(A[hi]-A[lo]). 32-bit overflows for large values.

X Not checking target in [A[lo],A[hi]] in loop condition.

O Without bounds check, pos can be outside [lo,hi] causing out-of-bounds access.