Algorithms

Specialized Search Algorithms

Binary search is optimal for sorted arrays when element distribution is unknown. But when data has special properties - uniform distribution, unbounded size, or unimodal structure - specialized algorithms can outperform binary search. This article covers five search techniques that exploit data characteristics for better performance.

πŸ“‹ At a Glance

AlgorithmBest CaseAverageWorst CaseBest For
InterpolationO(1)O(log log n)O(n)Uniformly distributed data
ExponentialO(1)O(log n)O(log n)Unbounded/unknown size arrays
JumpO(√n)O(√n)O(√n)When backward steps are expensive
FibonacciO(log n)O(log n)O(log n)When multiplication is expensive
TernaryO(log n)O(log n)O(log n)Unimodal functions (find max/min)

🎯 What You'll Learn

After reading this article, you will be able to:

  • Apply interpolation search when data is uniformly distributed
  • Use exponential search for unbounded or very large arrays
  • Implement ternary search for finding extrema in unimodal functions
  • Choose the right search algorithm based on data characteristics
  • Recognize when specialized searches outperform binary search
  • Avoid common pitfalls like applying ternary search to non-unimodal functions

πŸ”₯ Production Story: The Cache Key Lookup

A caching system stored 10 million sorted timestamps as keys for quick range queries. Binary search worked, but a performance-critical path needed faster lookups.

JAVA(5 lines)
Code
Loading syntax highlighter...
Analysis revealed:
  • Timestamps were roughly uniformly distributed (events over 24 hours)
  • Range was known: 0 to 86,400,000 (milliseconds in a day)
  • Data was dense - few gaps in the timeline
The optimization:
JAVA(39 lines)
Code
Loading syntax highlighter...
Results:
  • Binary search: 23 comparisons average
  • Interpolation search: 4 comparisons average
  • 5.75x fewer comparisons on uniform timestamp data
The lesson: When you know data distribution, exploit it. Interpolation search trades generality for speed on uniform data.

🧠 Mental Model: Choosing Search Algorithms

TEXT(20 lines)
Code
Loading syntax highlighter...

The Intuition

Binary search always checks the middle element. But if you're looking for "Smith" in a phone book, you don't open to the middle - you open closer to the back, where S names are.

Interpolation search uses the same idea: estimate position based on value.

TEXT(18 lines)
Code
Loading syntax highlighter...

Implementation

JAVA(82 lines)
Code
Loading syntax highlighter...

When Interpolation Search Fails

JAVA(19 lines)
Code
Loading syntax highlighter...

Interpolation Search Complexity Analysis

Data DistributionAverage CaseWorst Case
UniformO(log log n)O(n)
Linear (sorted by index)O(1)O(1)
ExponentialO(n)O(n)
Random (non-uniform)O(√n) to O(n)O(n)

The Problem

Binary search requires knowing array size upfront. What if:

  • Array size is unknown (streaming/infinite)
  • Array is very large but target is likely near the beginning
  • We want to find the bounds before searching

The Algorithm

Exponential search finds the range where target exists, then uses binary search within that range.

TEXT(18 lines)
Code
Loading syntax highlighter...

Implementation

JAVA(84 lines)
Code
Loading syntax highlighter...

Use Cases

JAVA(67 lines)
Code
Loading syntax highlighter...

The Concept

Ternary search finds the maximum or minimum of a unimodal function - one that increases then decreases (or vice versa).
TEXT(16 lines)
Code
Loading syntax highlighter...

Implementation

JAVA(74 lines)
Code
Loading syntax highlighter...

Golden Section Search (Optimized Ternary)

Golden section search is more efficient - it reuses one evaluation per iteration.

JAVA(37 lines)
Code
Loading syntax highlighter...

Common Applications

JAVA(54 lines)
Code
Loading syntax highlighter...

The Concept

Jump search jumps ahead by fixed steps, then does linear search backward. Useful when backward movement is cheap but random access is expensive.

TEXT(17 lines)
Code
Loading syntax highlighter...

Implementation

JAVA(70 lines)
Code
Loading syntax highlighter...

Why √n is Optimal

TEXT(15 lines)
Code
Loading syntax highlighter...

The Concept

Fibonacci search divides search space using Fibonacci numbers instead of halves. Useful when multiplication/division is expensive (some embedded systems).

TEXT(12 lines)
Code
Loading syntax highlighter...

Implementation

JAVA(56 lines)
Code
Loading syntax highlighter...
ScenarioBetter Choice
General purposeBinary search
No multiplication hardwareFibonacci search
Array much larger than cacheFibonacci (slightly better locality)
Teaching recursion patternsFibonacci

⚠️ Common Mistakes

Mistake 1: Interpolation on Non-Uniform Data

JAVA(12 lines)
Code
Loading syntax highlighter...

Mistake 2: Ternary Search on Non-Unimodal Function

JAVA(12 lines)
Code
Loading syntax highlighter...

Mistake 3: Jump Search with Wrong Step

JAVA(10 lines)
Code
Loading syntax highlighter...

Mistake 4: Integer Overflow in Interpolation

JAVA(6 lines)
Code
Loading syntax highlighter...

These implementations have bugs. Find and fix them:

JAVA(44 lines)
Code
Loading syntax highlighter...
πŸ’‘ Hint

Look for:

  1. Division by zero, overflow, bounds checking
  2. Logic inversion in ternary search
  3. Array bounds and target value bounds
βœ… Solution
JAVA(81 lines)
Code
Loading syntax highlighter...
Bugs explained:
  1. Interpolation: Division by zero when arr[hi] == arr[lo], overflow in (target - arr[lo]) * (hi - lo), and missing target bounds check.
  2. Ternary minimum: The condition logic was correct, but the update was inverted. For finding minimum with unimodal (decreasing then increasing), if f(m1) < f(m2), the minimum is in [lo, m2] not [m1, hi].
  3. Exponential: Missing bounds check bound < n causes ArrayIndexOutOfBoundsException. Also hi = bound should be hi = min(bound, n-1).

πŸ’» Exercises

Create a hybrid that uses interpolation for first few iterations, then switches to binary search if not converging.

JAVA(8 lines)
Code
Loading syntax highlighter...

Exercise 2: Ternary Search for Bitonic Array Peak ⭐⭐

Find the maximum element in a bitonic array (increases then decreases).

JAVA(9 lines)
Code
Loading syntax highlighter...

Search that expands both directions from a starting point (useful when target is near a known position).

JAVA(9 lines)
Code
Loading syntax highlighter...

Exercise 4: Search in Nearly Sorted Array ⭐⭐⭐

Array where each element is at most k positions from its sorted position.

JAVA(10 lines)
Code
Loading syntax highlighter...
πŸ’‘ Hint

For each position, check arr[mid-k] to arr[mid+k]. Combine with exponential search ideas.


For very large datasets, use hierarchical interpolation: first interpolate on a sampled summary, then search in the identified block.

JAVA(14 lines)
Code
Loading syntax highlighter...

🎀 Interview Questions

Answer:

Interpolation search is better when:

  1. Data is uniformly distributed: O(log log n) vs O(log n)
  2. Comparison is cheap but iterations are expensive: Fewer iterations matter
  3. Data range is known: Can compute accurate position estimate

Binary search is better when:

  1. Distribution unknown or non-uniform: Interpolation degrades to O(n)
  2. Data is adversarial: Binary search is always O(log n)
  3. Simplicity matters: Binary search is easier to implement correctly
Example numbers for n = 1,000,000:
  • Binary search: ~20 comparisons
  • Interpolation (uniform): ~4 comparisons
  • Interpolation (exponential data): ~1,000,000 comparisons!

Answer:
Binary search: Find element in sorted array (or find boundary)
  • Input: sorted array or monotonic predicate
  • Output: position or boundary
Ternary search: Find extremum (max/min) in unimodal function
  • Input: unimodal function
  • Output: x that maximizes/minimizes f(x)
Key difference: Binary search works with monotonic (always increasing or always decreasing), ternary search works with unimodal (increases then decreases, or vice versa).
Cannot use binary search for: "Find x that maximizes f(x) where f increases then decreases" - there's no sorted order.
Cannot use ternary search for: "Find 5 in sorted array" - the array isn't unimodal, it's monotonic.

Question 3: How would you search an infinite sorted array?

Answer:

Use exponential search:

  1. Find bounds: Start at index 1, double until arr[bound] >= target or bound exceeds array size.
  2. Binary search: Search in range [bound/2, bound].
JAVA(18 lines)
Code
Loading syntax highlighter...
Time complexity: O(log p) where p is target position
  • Finding bound: O(log p) iterations
  • Binary search: O(log p) iterations
  • Total: O(log p)

Answer:
AspectJump SearchBinary Search
TimeO(√n)O(log n)
Access patternSequential forward, then backwardRandom access
Best forSequential storage (tape, disk)Random access (RAM)
SimplicitySimplerSlightly more complex
When jump search wins: Storage where sequential access is much faster than random access. On magnetic tape, jumping forward is fast but seeking to arbitrary position is slow.
Interesting fact: For linked lists, jump search (with pointers every √n nodes) is optimal: O(√n) vs O(n) for binary search (which needs O(n) to reach middle).

Question 5: Design a search for a sorted array where elements repeat

Answer:

For arrays with many duplicates, consider:

  1. Block-based search: Jump by blocks, since many elements are equal.
  2. Interpolation with density estimation:
JAVA(4 lines)
Code
Loading syntax highlighter...
  1. Galloping/exponential for bounds:
JAVA(6 lines)
Code
Loading syntax highlighter...
  1. For counting occurrences: Use lower/upper bound (Part 8), which handles duplicates naturally.
Special case - all elements equal: Both binary and interpolation degenerate. Need to just scan or use count information.

πŸ“‹ Quick Reference

Algorithm Selection

ConditionBest Algorithm
Sorted array, generalBinary search
Sorted, uniform dataInterpolation search
Size unknown/unboundedExponential search
Sequential access onlyJump search
No multiplicationFibonacci search
Find max/min of unimodalTernary search

Complexity Comparison

AlgorithmBestAverageWorstFunction Calls
BinaryO(log n)O(log n)O(log n)logβ‚‚(n)
InterpolationO(1)O(log log n)O(n)varies
ExponentialO(1)O(log n)O(log n)2β‹…logβ‚‚(p)
JumpO(1)O(√n)O(√n)2√n
FibonacciO(log n)O(log n)O(log n)log_Ο†(n)
TernaryO(log n)O(log n)O(log n)2β‹…log₃(n)

Quick Formulas

SearchPosition Formula
Binarymid = lo + (hi - lo) / 2
Interpolationpos = lo + (target - arr[lo]) Γ— (hi - lo) / (arr[hi] - arr[lo])
Jumpstep = √n
Ternarym1 = lo + (hi - lo) / 3, m2 = hi - (hi - lo) / 3
Golden Sectionm1 = hi - (hi - lo) / Ο†, m2 = lo + (hi - lo) / Ο†

πŸ“… Review Schedule

DayFocusTime
Day 1Read article, understand when to use each algorithm60 min
Day 3Implement interpolation and exponential search30 min
Day 7Implement ternary search, solve unimodal problems30 min
Day 14Debug exercise + compare performance20 min
Day 30Quiz: which algorithm for which scenario10 min

πŸ”— What's Next?

Part 10: String Searching Algorithms covers:
  • Naive approach and its limitations
  • KMP (Knuth-Morris-Pratt) algorithm
  • Rabin-Karp with rolling hash
  • Boyer-Moore for practical performance
  • Aho-Corasick for multiple patterns
  • Java's String.indexOf() internals
Key insight preview: String searching is ubiquitous - log parsing, text editors, DNA sequencing. The right algorithm can be 10-100x faster than naive search.

This article is part of the Algorithms Compendium series. For the complete learning path, see Part 0: How to Use This Series.