Beginner~8 min

Find Peak Element

How to find A local maximum in an unsorted array in O(log n) — not the biggest value overall, just one that beats both its neighbors.

The job

You have an array of numbers with no ordering guarantee. Find the index of ANY "peak" — a value that is not smaller than either of its immediate neighbors.

The obvious way

Scan left to right, checking every value against both its neighbors.A list of 1,000,000 can cost 1,000,000 checks — surprising, since the array is not even sorted.

The idea

Compare the middle value to the one right after it. If it is smaller, the slope is going uphill, and following uphill is GUARANTEED to reach a peak — so the peak is somewhere to the right. Otherwise, the slope has stopped climbing right here, so mid itself qualifies as a peak candidate and everything strictly to its right can be dropped.

Think of it like this. Hiking in fog with no map, trying to reach any hilltop. At every step you only need to know whether the ground ahead of you is rising or falling — always walk uphill, and you are mathematically guaranteed to reach a peak, without ever needing to see the whole mountain range at once.

Climbing toward any peak

lo
hi
looks
Still in play
/ 4

4 numbers, no order required. A "peak" is any value not smaller than both its neighbors — find one.

0.0s/ 11.9s
find_peak.pypython
def find_peak(nums):
    lo, hi = 0, len(nums) - 1
    while lo < hi:
        mid = (lo + hi) // 2
        if nums[mid] < nums[mid + 1]:
            lo = mid + 1
        else:
            hi = mid
    return lo

This run

Peak found at index 2, value 3 — found in 2 looksinstead of scanning all 4.

Try:

Why this works on an unsorted array

Slope, not sortedness

The only thing being compared is mid to its immediate neighbor — a purely LOCAL fact. Global sortedness was never required.

Uphill always leads somewhere

Treating the array's edges as negative infinity guarantees that walking uphill must eventually stop rising — and the point where it stops is a peak, by definition.

Any peak, not the biggest

The problem only asks for A peak. Two-Peaks presets show this clearly — different runs can legitimately converge on different valid answers.

How to spot this shape

The tell: You need any index satisfying a LOCAL comparison to its neighbor(s), and following the direction that comparison points is guaranteed to reach a valid answer.

Reach for it when

  • The problem asks for "a" peak/valley/local extremum, not "the" global one.
  • The array has no sortedness guarantee at all.
  • A single comparison between mid and an adjacent element tells you which half to keep.
  • The array's edges are implicitly treated as extreme (negative or positive infinity).

Not this when

  • You need the GLOBAL maximum or minimum — that needs a full scan, since no local rule finds it in log time.
  • You need every peak, not just one.
  • Ties or plateaus make "strictly uphill" ambiguous in a way the problem cares about.

Practice

6 problems
LeetCodeO(log n) / O(1)

The lesson, exactly. Compare mid to mid+1: uphill means a peak is to the right, flat-or-downhill means mid could be it.

LeetCodeO(log n) / O(1)

A guaranteed single peak (strictly up then strictly down) — the exact same search, with a friendlier guarantee.

LeetCodeO(log n) / O(1)

The same "keep mid, compare to a neighbor/endpoint" shape, hunting a valley's rotation point instead of a peak — its own lesson here too.

LeetCodeO(log n) / O(1)

Find the peak first with this exact search, then binary search each of the two monotonic halves for the target.

LeetCodeO(m log n) / O(1)

The 2D generalization: binary search columns, and within each candidate column find the row maximum to decide which way to move.

LeetCodeO(log(m+n)) / O(1)

A different property entirely (a balanced partition point), but the same halve-based-on-a-local-comparison instinct.