Jump Search
Search a sorted array by jumping ahead in fixed blocks of size √n, then scanning linearly within the block.
Overview
Jump search works on a sorted array by stepping forward in blocks of size m (optimally m = √n) until it finds a block whose last element is ≥ the target, then scanning that block linearly. It costs O(√n) comparisons — between Linear Search and Binary Search.
Its selling point is that it only ever moves forward, so it suits media where jumping backwards is expensive (tape, sequential storage, singly linked lists with a skip index) and it makes fewer far jumps than binary search.
Intuition
A mental model before the formal terms.
Looking for page 347 in a book with no index: flip ahead 20 pages at a time until you pass 347, then step back and turn single pages. With 400 pages you flip at most 20 big jumps plus 20 single pages, not 400.
How it works
- Choose the block size
m = ⌊√n⌋. - Set
prev = 0,step = m. Whilea[min(step, n) - 1] < target:prev = step,step += m. Ifprev >= n, the target is absent. - Linear-scan from
prevwhilea[prev] < target; stop when reachingmin(step, n). - If
a[prev] == target, returnprev; otherwise return-1.
Why it works
Because the array is sorted, the target can only lie in the first block whose last element is ≥ the target — every earlier block ends below it.
At most n/m jumps plus at most m - 1 linear steps; minimizing n/m + m gives m = √n and a total of 2√n comparisons.
Recognition
How to tell a problem wants this.
- Sorted data on a medium where backward seeks are costly or forbidden.
- The problem asks for something better than linear but you cannot use random access freely (e.g. an indexed sequential file).
- Rarely the intended answer in interviews — it appears mostly as a discussion of the √n decomposition idea.
Interactive visualization
Play, step, change the input. ← → and space work too.
1step = floor(sqrt(n)); prev = 02while a[min(step, n) - 1] < target:3 prev = step; step += floor(sqrt(n))4 if prev >= n: return -15for i in prev .. min(step, n) - 1:6 if a[i] == target: return i7return -1Pseudocode
1m = floor(sqrt(n)); prev = 0; step = m2while a[min(step, n) - 1] < target:3 prev = step; step += m4 if prev >= n: return -15while a[prev] < target:6 prev += 17 if prev == min(step, n): return -18if a[prev] == target: return prev9return -1Implementations
1import math2from typing import Sequence3 4 51 · Step forward in blocks of sqrt(n) until the block could contain target6def jump_search(a: Sequence[int], target: int) -> int:7 n = len(a)8 if n == 0:9 return -110 step = max(1, math.isqrt(n))11 12 prev, curr = 0, step13 while prev < n and a[min(curr, n) - 1] < target:14 prev = curr15 curr += step16 if prev >= n:17 return -1 # ran off the end without reaching target18 192 · Scan the identified block linearly; it holds at most step elements20 end = min(curr, n)21 for i in range(prev, end):22 if a[i] == target:23 return i24 if a[i] > target:25 break # sorted, so no later element can match26 return -127 28 293 · Why sqrt(n): n/step jumps plus step scans, minimised at step = sqrt(n)30def worst_case_probes(n: int, step: int) -> int:31 return n // step + step # minimal at step = sqrt(n), giving 2*sqrt(n)32 33 344 · On a random-access list binary search dominates; jump search is for35# sequential sources where seeking backward is expensive or impossible36def block_count_for(n: int) -> int:37 return math.ceil(n / math.sqrt(n))math.isqrt(n)is the exact integer square root — no float round-trip, no rounding error, available since Python 3.8.prev, curr = 0, stepuses tuple assignment for the two cursors, matching how the loop advances them together.a[min(curr, n) - 1]clamps the block-end probe exactly as in the other languages.range(prev, end)is half-open, which lines up withend = min(curr, n)being one past the last index to scan.- The
breakona[i] > targetexploits sortedness to cut the average block scan in half.
bisect is O(log n) and runs in C, so on a real list it beats this by a wide margin — jump search is for sequential sources.
math.isqrtreturns the floor of the exact square root for arbitrarily large integers, unlikeint(math.sqrt(n))which loses precision past 2^53.math.sqrtreturns a float and raisesValueErroron negatives;isqrtraises on negatives too but never rounds.- For a genuinely sequential source,
itertools.isliceexpresses "skip step items" without materialising them. bisect_leftis the right tool for any in-memory sorted list; this algorithm earns its place only when random access is expensive.
- Using
int(math.sqrt(n))on a hugen, where float rounding can produce a step one too large and skip the target block. - Writing
range(prev, end + 1), which reads one element past the block and, on the last block, past the list. - Forgetting the
if prev >= n: return -1guard, so a target above the maximum loops untilmin(curr, n) - 1stops moving.
- Integer square root: Python has exact
math.isqrt; C++, JavaScript and TypeScript go through adoublesqrtand floor it, which is exact only below 2^53. - Clamping: C++
std::minrequires matching types and needs explicit casts, whileMath.minand Pythonminaccept anything and coerce or compare directly. - The practical verdict is the same everywhere —
std::lower_bound,bisect_left, or a hand-written binary search beats this on any random-access container. - Where it does win differs by ecosystem: paged network fetches in JS/TS,
std::forward_listor memory-mapped tape in C++, and generator pipelines withitertools.islicein Python.
Complexity
At most 2√n comparisons with block size √n.
Compare growth rates in the Complexity Explorer →When to use — and when not to
- Sorted data where jumping backwards is expensive — sequential-access storage, tapes, one-directional cursors.
- When the number of far jumps matters more than total comparisons (each jump is a costly seek).
- As an intermediate technique to introduce √n decomposition.
- Ordinary in-memory sorted arrays — Binary Search is
O(log n)and just as simple. - Unsorted data; the block test relies on sortedness.
- Unbounded or unknown-length inputs — use Exponential Search.
Alternatives
Common mistakes
- Indexing
a[step - 1]past the end on the last block — always clamp withmin(step, n). - Using block size
n/2or a constant instead of√n, losing theO(√n)bound. - Not handling the empty array or a target larger than every element.
Interview patterns
- Explain the
n/m + mtrade-off and derivem = √n— a warm-up for √n decomposition and Mo's algorithm. - Compare seek counts: jump search makes ≤ √n forward seeks, binary search makes log n seeks that alternate direction.
- Recognizing the approach from an array and a targetIntermediate
- Deciding whether O(n²) can be improvedIntermediate
- Where does O(n log n) come from?Beginner
- Questions to ask before binary searchingIntermediate
- Minimum Size Subarray SumIntermediate
- Search in Rotated Sorted ArrayIntermediate
Example problems
No linked problems yet.