162. Find Peak Element - Detailed Explanation
Problem statement
Given an array of integers nums, a peak element is an element that is strictly greater than its neighbors. You need to find a peak element and return its index. If the array contains several peaks, the index of any one of them is acceptable.
Additional details:
- You may assume that
nums[-1]andnums[n]are negative infinity, where n is the length of the array. Those positions do not exist, and treating them as negative infinity guarantees that at least one peak exists. - The input array can hold a single element, which is trivially a peak.
Example inputs, outputs, and explanations
-
Example 1:
- Input:
nums = [1,2,3,1]. - Output:
2. - Explanation: The element at index 2 is
3, which is greater than its neighbors2and1.
- Input:
-
Example 2:
- Input:
nums = [1,2,1,3,5,6,4]. - Output: Could be
1or5. - Explanation:
- At index 1, the element is
2, with neighbors1and1, so2is a peak. - At index 5, the element is
6, with neighbors5and4, so6is also a peak.
- At index 1, the element is
- Input:
-
Example 3 (edge case):
- Input:
nums = [1]. - Output:
0. - Explanation: With only one element, it is a peak by definition.
- Input:
Constraints
- The length of
numsis at least 1. - You can assume that
nums[i]is not equal tonums[i+1]for all valid indices, which rules out plateaus. - An optimal solution is expected to run faster than O(n), ideally in O(log n).
This question is an instance of the modified binary search pattern. Classic binary search needs a sorted array, while a modified binary search keeps the halving step and swaps in a different test for deciding which half to keep. Here the test is a single comparison between a neighbor pair. The pattern applies well beyond this one problem, and the summary of the most common LeetCode patterns shows how often it appears.
Hints to approach the solution
-
Directional clues from neighbors:
- If an element is less than its right neighbor, a peak has to exist on the right side. The values are climbing, and the climb cannot continue past the end of the array.
- If an element is greater than its right neighbor, a peak has to lie on the left, and it may be the current element itself.
-
Binary search opportunity:
- Given that observation, you can compare the middle element with its neighbor and decide which half of the array still contains a peak. That decision discards half the candidates per step.
Approach 1: linear scan (brute force)
Explanation
- Method:
- Traverse the array from left to right and test each element for the peak property.
- For each index
i, verify thatnums[i]is greater than bothnums[i-1], wheni > 0, andnums[i+1], wheni < n-1.
- Edge handling:
- Handle the first and last elements separately, since each has only one neighbor.
Pseudocode
if length(nums) == 1: return 0 if nums[0] > nums[1]: return 0 if nums[n-1] > nums[n-2]: return n-1 for i in range(1, n-1): if nums[i] > nums[i-1] and nums[i] > nums[i+1]: return i
Downsides:
- This approach runs in O(n) time. That is acceptable for small inputs, but it does not meet the O(log n) target the problem sets.
Approach 2: binary search (optimal)
Explanation
- Method:
- Use binary search to shrink the search space.
- At each iteration, compare the middle element with its right neighbor.
- If
nums[mid] > nums[mid+1], a peak exists in the left half, includingmiditself. - Otherwise, a peak exists in the right half.
- If
- Continue until the search space narrows to one element, which is a peak.
- Why it works:
- Peaks are defined by strict inequality, and the boundaries
nums[-1]andnums[n]count as negative infinity. Together those two facts mean the half you keep always still contains a peak, so binary search can move toward one safely.
- Peaks are defined by strict inequality, and the boundaries
Pseudocode
left = 0, right = n - 1 while left < right: mid = (left + right) // 2 if nums[mid] > nums[mid + 1]: right = mid else: left = mid + 1 return left
Detailed walkthrough (visual example)
Consider the input nums = [1,2,3,1]:
| Step | left | right | mid | Comparison | Decision |
|---|---|---|---|---|---|
| Initialization | 0 | 3 | n/a | n/a | n/a |
| Iteration 1 | 0 | 3 | 1 | Compare 2 and 3 | Since 2 < 3, set left = mid + 1, so left becomes 2 |
| Iteration 2 | 2 | 3 | 2 | Compare 3 and 1 | Since 3 > 1, set right = mid, so right becomes 2 |
| Termination | 2 | 2 | n/a | n/a | Return left, index 2 |
The element at index 2 is 3, which is a peak.
Code implementations
Python code
Java code
Complexity analysis
-
Time complexity:
- Brute force (linear scan): O(n) in the worst case.
- Binary search (optimal): O(log n), because the search space halves on every iteration.
-
Space complexity:
- Both approaches use O(1) additional space.
Common mistakes and edge cases
Common mistakes
- Boundary conditions:
- Not handling the first and last elements correctly.
- Off-by-one errors in the binary search bounds. Note that the loop keeps
midas a candidate when it setsright = mid, and excludes it when it setsleft = mid + 1.
- Incorrect assumptions:
- Assuming the global maximum is required. Any local peak is an accepted answer.
Edge cases
- Single element array:
- The only element is automatically a peak.
- Strictly increasing or decreasing array:
- In a strictly increasing array, the last element is a peak.
- In a strictly decreasing array, the first element is a peak.
Alternative variations and related problems
Variations
- Find all peak elements:
- Instead of returning one peak, you might be asked for the indices of every peak in the array. Binary search no longer applies, since a full scan is the only way to report them all.
- Finding valleys:
- A variation asks for a valley, an element strictly less than its neighbors. Flip the comparison and the same halving argument holds.
Related problems for further practice
- Search in Rotated Sorted Array: Another array that is not sorted end to end, yet still yields to a halving decision. It appears on the Blind 75 list, which is a good place to see how many questions reduce to this pattern.
- Koko Eating Bananas: The Koko Eating Bananas answer runs a binary search over an answer range rather than over array indices, which is the next step up in the same family.
- Longest Increasing Subsequence: A dynamic programming question that shares the vocabulary of rising and falling runs, but not the technique.
- Container With Most Water: A two pointers question, useful as a contrast with the halving decision used here.
The course Grokking the Coding Interview teaches modified binary search alongside the other patterns, including the variants where the array is rotated or the search bounds are unknown.

GET YOUR FREE
Coding Questions Catalog

$99

$197

$72