A peak element is an element that is strictly greater than its neighbors.
Given a 0-indexed integer array nums
, find a peak element, and return its index. If the array contains multiple peaks, return the index to any of the peaks.
You may imagine that nums[-1] = nums[n] = -∞
. In other words, an element is always considered to be strictly greater than a neighbor that is outside the array.
You must write an algorithm that runs in O(log n)
time.
Example 1:
Input: nums = [1,2,3,1] Output: 2 Explanation: 3 is a peak element and your function should return the index number 2.
Example 2:
Input: nums = [1,2,1,3,5,6,4] Output: 5 Explanation: Your function can return either index number 1 where the peak element is 2, or index number 5 where the peak element is 6.
Constraints:
1 <= nums.length <= 1000
-231 <= nums[i] <= 231 - 1
nums[i] != nums[i + 1]
for all valid i
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We're trying to find a value that is larger than its neighbors. The brute force approach simply checks every single value to see if it fits the criteria.
Here's how the algorithm would work step-by-step:
def find_peak_element_brute_force(numbers):
for index in range(len(numbers)):
# Check if the current element is greater than the next element
if index == len(numbers) - 1:
next_element = float('-inf')
else:
next_element = numbers[index + 1]
# Check if the current element is greater than the previous element
if index == 0:
previous_element = float('-inf')
else:
previous_element = numbers[index - 1]
# If both neighbors are smaller, then we found the peak
if numbers[index] > next_element and numbers[index] > previous_element:
return index
return -1
The goal is to quickly find a peak in a set of numbers. Instead of checking every number, which would take a long time, we use a divide-and-conquer strategy to zoom in on the peak efficiently.
Here's how the algorithm would work step-by-step:
def find_peak_element(numbers):
left_index = 0
right_index = len(numbers) - 1
while left_index < right_index:
middle_index = (left_index + right_index) // 2
# Check if the middle element is a peak.
if numbers[middle_index] > numbers[middle_index + 1]:
# If middle is greater, peak is in left half.
right_index = middle_index
else:
# Peak is in the right half.
left_index = middle_index + 1
# At the end of the search, leftIndex is the peak.
return left_index
Case | How to Handle |
---|---|
Empty or null input array | Return -1 immediately since no peak can exist in an empty array. |
Array with only one element | Return index 0, as a single element is trivially a peak. |
Array with two elements, one larger than other | Return index of larger element, the larger of the two will be peak. |
Peak at the beginning of the array (index 0) | The algorithm should correctly identify the peak if nums[0] > nums[1]. |
Peak at the end of the array (index nums.length - 1) | The algorithm should correctly identify the peak if nums[nums.length - 1] > nums[nums.length - 2]. |
Array with all elements equal | Return index 0, as any element can be considered a peak if neighbors are equal. |
Large array where elements are sorted in ascending order | Binary search approach is efficient for large arrays, but needs adjustment when there is no peak (i.e., strictly increasing). |
Negative numbers in the array | The comparison logic should work correctly with negative numbers without modification. |