Quant Memo
Core

Searching a Unimodal Function

How to find the peak (or trough) of a function that rises then falls using far fewer evaluations than checking every point — the ternary-search technique, and why it needs unimodality to work.

Prerequisites: Binary Search Patterns

You're handed a function you can only evaluate point by point (no formula, no derivative) and told it's unimodal on an interval — it strictly increases, hits one peak, then strictly decreases, with no other bumps. Where's the peak? Checking every point is wasteful. The right tool is a cousin of binary search, adapted for a peak instead of a sorted target: ternary search.

Why two probe points are enough

Pick two points m1<m2m_1 < m_2 inside the current interval [lo,hi][lo, hi], evenly spaced so they split it into thirds. Because the function is unimodal, comparing f(m1)f(m_1) and f(m2)f(m_2) tells you which third of the interval can be safely thrown away:

  • If f(m1)<f(m2)f(m_1) < f(m_2), the peak cannot lie to the left of m1m_1 — the function is still climbing at m1m_1 (or the peak is between m1m_1 and m2m_2), so discard [lo,m1)[lo, m_1) and search [m1,hi][m_1, hi].
  • If f(m1)>f(m2)f(m_1) > f(m_2), symmetric reasoning discards (m2,hi](m_2, hi] and you search [lo,m2][lo, m_2].

In plain English: two probes are enough to identify which side is "still going uphill," and unimodality guarantees the peak must be on that side or between the probes — never on the strictly-downhill side you just discarded. Each round shrinks the interval to two-thirds of its previous size, so after kk rounds the interval is (2/3)k(2/3)^k of its original width — shrinking to arbitrary precision in a number of steps that grows only logarithmically with how precise you need to be.

Worked example: finding the peak of f(x)=(x4)2+10f(x) = -(x-4)^2 + 10 on [0,10][0, 10]

This is unimodal with true peak at x=4x=4. Round 1: lo=0,hi=10lo=0, hi=10, probes m1=3.33m_1 = 3.33, m2=6.67m_2=6.67. f(3.33)=(0.67)2+109.55f(3.33) = -(0.67)^2+10\approx9.55, f(6.67)=(2.67)2+102.87f(6.67)=-(2.67)^2+10\approx2.87. Since f(m1)>f(m2)f(m_1) > f(m_2), discard the right third: new interval [0,6.67][0, 6.67]. Round 2: lo=0,hi=6.67lo=0,hi=6.67, probes m1=2.22,m2=4.44m_1=2.22, m_2=4.44. f(2.22)=(1.78)2+106.83f(2.22)=-(1.78)^2+10\approx6.83, f(4.44)=(0.44)2+109.80f(4.44)=-(0.44)^2+10\approx9.80. Now f(m1)<f(m2)f(m_1) < f(m_2), so discard the left third: new interval [2.22,6.67][2.22, 6.67]. Notice the true peak, x=4x=4, is inside [2.22,6.67][2.22,6.67] at every step — after just two rounds the search window has already shrunk from width 10 to width 4.44, and it keeps shrinking by a factor of 2/32/3 every round from here.

Function explorer
-2222.0
x = 1.00f(x) = 2.000

Adjust the curve and imagine dropping two probe points inside the visible window: comparing their heights always tells you which side to discard, because a single-peaked curve can never have its true maximum on the strictly-descending side of either probe.

What this means in practice

Ternary search is the go-to technique whenever an interview question describes a "one hump" relationship — profit that rises then falls as you increase price, accuracy that rises then falls as you tune a single hyperparameter, PnL that rises then falls with position size — and you need the optimal point using few evaluations, especially when each evaluation is expensive (a backtest run, a live query). It generalizes the "cut the search space in half" instinct from binary search to "cut it to two-thirds," using a comparison of function values instead of a comparison against a fixed target.

For a unimodal function on an interval, two evenly spaced probe points let you discard one-third of the interval each round — the side where the function is provably still descending. Repeating this (ternary search) narrows in on the peak in roughly log3/2\log_{3/2} rounds instead of a full linear scan.

Ternary search silently gives a wrong answer if the function isn't actually unimodal — even one extra local bump can hide the true peak in a discarded third. Always confirm (or be explicitly told) that the function has exactly one hump before trusting this technique; a quick plot or a monotonicity check is worth doing first.

Related concepts

Practice in interviews

Further reading

  • Cormen et al., Introduction to Algorithms, ch. 2 (binary search generalizations)
ShareTwitterLinkedIn