No sorted structure — just a slope property. Follow the uphill direction and binary search guarantees you land on a peak.
A peak element is an element strictly greater than its neighbors. Given an integer array nums where nums[i] != nums[i+1], return the index of any peak element. The array is virtually bounded by -∞ on both sides. Must run in O(log n).
The array doesn't need to be sorted. The key invariant: if nums[mid] < nums[mid+1], we are on an upward slope — a peak must exist to the right. If nums[mid] > nums[mid+1], we are descending — a peak is at mid or to the left. In either case, we safely discard half the array.
Think of it as hiking. If the trail goes uphill ahead, keep walking right. If it goes downhill, the top is behind you. You always converge on a summit.
3 < 5 → uphill → peak is to the right. left = 4.
6 > 4 → downhill → peak is mid or to the left. right = 5.
5 < 6 → uphill → peak to the right. left = 5.
left == right → return 5. nums[5]=6 is indeed a peak.
class Solution { public int findPeakElement(int[] nums) { int left = 0, right = nums.length - 1; while (left < right) { // strict: converges to single element int mid = left + (right - left) / 2; if (nums[mid] < nums[mid + 1]) left = mid + 1; // uphill — peak is to the right else right = mid; // downhill — peak is mid or left } return left; // left == right == peak index } }
class Solution: def findPeakElement(self, nums: list[int]) -> int: left, right = 0, len(nums) - 1 while left < right: # strict: converges to single element mid = left + (right - left) // 2 if nums[mid] < nums[mid + 1]: left = mid + 1 # uphill — peak is to the right else: right = mid # downhill — peak is mid or left return left # left == right == peak index
Note while left < right: This variant converges left and right to the same index without needing a saved boundary variable. When they meet, that index is the peak. It works because we never set right = mid - 1 — we always keep mid as a candidate.