Higher Ground
A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- medium
- Seniority
- L4
- Asked in
- Spirit Airlines
Problem
You're scanning a buffer of unsorted sensor readings for a peak: any index in nums whose value is strictly greater than both of its neighbors, where the space just past either end of the buffer counts as lower than any reading. Return the index of any one such peak. The buffer can be large and lookups must stay logarithmic, so walking every reading is off the table.
Somewhere the ground stops climbing.
Example 1
Input:
nums = [1,2,3,1]
Output:
2
Example 2
Input:
nums = [1,2,1,3,5,6,4]
Output:
5
Worked solution and explanation
What this really is
Strip the mountain imagery and this is binary search with no sorted array to lean on. Most candidates freeze right here: 'binary search needs sorted data, so I'll just scan for the max in O(n).' That reflex misses the one fact that cracks the problem. Any index whose value rises toward its right neighbor guarantees a peak somewhere to the right, because the buffer cannot climb forever past a boundary that counts as negative infinity. That single gradient check, not any global order, is what lets you throw away half the buffer every step.
Break down the requirements
Step 1: Set up the search boundaries
left starts at 0, right at len(nums) - 1. The invariant you are protecting: a peak always lives somewhere in the closed range [left, right].
Step 2: Compare the midpoint with its right neighbor
Compute mid. If nums[mid] < nums[mid + 1], the slope is rising, so a peak lies strictly to the right: move left to mid + 1. Otherwise mid could be the peak itself, so move right to mid and keep it in range.
Step 3: Terminate when the window collapses
When left == right the window has collapsed to one index, and the invariant guarantees that index is a peak. Return it.
The solution
def find_peak_element(nums: list) -> int:
left = 0
right = len(nums) - 1
while left < right:
mid = (left + right) // 2
if nums[mid] < nums[mid + 1]:
left = mid + 1
else:
right = mid
return leftNo sorted assumption anywhere: the comparison reads the slope, not the order.
Common follow-up questions
- What if the buffer could contain plateaus of consecutive equal values? (Tests that the strict 'greater than both neighbors' guarantee is what preserves O(log n).)
- How would you return every peak index instead of just one? (Tests that enumerating every peak forces an O(n) pass since no candidate can be skipped.)
- What if this were a 2D grid and you needed a peak cell? (Tests extending the gradient idea to two dimensions with a column-max reduction.)
- Why does this work even though the buffer is never sorted? (Tests the core insight that local gradient information, not global order, drives the halving.)