Find Peak Element

medium

A peak is an element that is strictly greater than its neighbours.

You are given a 0-indexed integer array nums. Return the index of any peak element — if the terrain has several summits, any one of them is a correct answer.

Treat the positions just outside the array as bottomless cliffs: imagine nums[-1] and nums[n] are both -∞. A boundary element therefore only needs to beat its one real neighbour. No two adjacent elements are equal.

Your algorithm must run in O(log n) time.

Hints

You only need an element that beats its two neighbours — not the global maximum. What does the required O(log n) whisper about the technique, even though the array is not sorted?
Stand at any middle index and compare nums[mid] with nums[mid + 1]. If the ground rises to the right, can the right half really contain no peak? Remember the array ends in a virtual cliff of negative infinity.
Binary search on the slope: while lo < hi, take mid; if nums[mid] > nums[mid + 1] a peak lies at mid or left (hi = mid), otherwise strictly right (lo = mid + 1). When lo == hi, that index is a peak.

Common doubts

Binary search never truly required sorted data; it requires a way to look at the middle and discard half with certainty. Here the slope at mid provides that certainty: a rising slope proves a peak exists to the right, a falling slope proves one exists at mid or to the left. Sortedness is just the most familiar source of such a guarantee.
The global maximum of the array is strictly greater than every other element, so it beats its own neighbours — and the virtual -∞ walls mean even a maximum sitting on the boundary qualifies. Every array of distinct-neighbour values has at least one peak.
No. The loop runs only while lo < hi, so mid = (lo + hi) / 2 always satisfies mid < hi <= n - 1, which makes mid + 1 <= n - 1 a valid index.
Some valid peak, not necessarily the first or the tallest. That is fine: the problem accepts the index of any peak, and that freedom is exactly what makes the halving argument legal.

Interview follow-ups

The slope at mid can be flat, so neither half can be safely discarded — an adversary can hide the peak on either side. In the worst case (all values equal except one) any algorithm needs O(n) looks. Discussing this degradation is exactly what the interviewer wants to hear.
Binary search over columns: take the middle column, find its maximum in O(rows), and compare that cell with its left and right neighbours. Move toward the larger side — the same rising-slope certificate in two dimensions. That is the problem Find a Peak Element II, running in O(rows · log(cols)).
No. On arbitrary unsorted data an adversary argument shows every unexamined element could secretly be the maximum, forcing Ω(n) looks. The relaxation from the maximum to any peak is precisely what buys the logarithmic bound.

Fun facts

  • Peak finding is the famous opening example of MIT's introductory algorithms course — chosen precisely because it demolishes the myth that binary search needs a sorted array.
  • The walk-uphill certificate is a discrete cousin of hill climbing in optimization: gradient ascent also promises only a local maximum, not the global one — and for the same reason.
  • The same keep-the-certain-half reasoning powers Find Minimum in Rotated Sorted Array, Search in Rotated Sorted Array, and the 2-D grid variant Find a Peak Element II.

Asked at

GoogleAmazonMetaMicrosoftBloombergUber
Frequently Sometimes Occasionally
Example 1
Input: nums = [1,2,3,1]
Output: 2
nums[2] = 3 is greater than both neighbours (2 and 1), so index 2 is a peak.
Example 2
Input: nums = [1,2,1,3,5,6,4]
Output: 5
There are two peaks: index 1 (value 2) and index 5 (value 6). Returning either index is accepted.
Example 3
Input: nums = [5,4,3,2,1]
Output: 0
The virtual cliff before index 0 counts as -∞, so nums[0] = 5 only has to beat nums[1] = 4.
Constraints

- 1 <= nums.length <= 1000 - -2^31 <= nums[i] <= 2^31 - 1 - nums[i] != nums[i + 1] for all valid i

Solve this problem →