class Solution:
def findPeakElement(self, nums):
left, right = 0, len(nums) - 1
while left < right:
mid = (left + right) // 2
if nums[mid] < nums[mid + 1]:
left = mid + 1
else:
right = mid
return left
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int left = 0, right = nums.size() - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < nums[mid + 1])
left = mid + 1;
else
right = mid;
}
return left;
}
};
class Solution {
public int findPeakElement(int[] nums) {
int left = 0, right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < nums[mid + 1])
left = mid + 1;
else
right = mid;
}
return left;
}
}
var findPeakElement = function(nums) {
let left = 0, right = nums.length - 1;
while (left < right) {
let mid = Math.floor((left + right) / 2);
if (nums[mid] < nums[mid + 1]) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
};
Given an array of integers nums
, find a peak element and return its index. A peak element is an element that is strictly greater than its neighbors.
nums[-1] = -∞
and nums[n] = -∞
where n
is the length of the array.
Your task is to return the index of any peak element in nums
.
The simplest way to solve this problem is to scan through the array and check for each element if it is greater than its neighbors. This is the brute-force approach, but it is not efficient for large arrays.
However, the problem hints at a more efficient solution. Since we only need any peak and not all of them, and since the array can be unsorted, we can use a modified binary search to find a peak in logarithmic time. The key is to compare the middle element with its neighbors and decide which direction to search next.
This is similar to climbing a mountain: if you're standing at a point and the next point is higher, you keep moving in that direction until you reach a peak.
left
and right
, at the start and end of the array.
left < right
:
mid = (left + right) // 2
(or language equivalent).nums[mid]
and nums[mid + 1]
:nums[mid] < nums[mid + 1]
, it means there is a peak to the right, so move left
to mid + 1
.mid
or to the left, so move right
to mid
.left == right
, this index is a peak, so return left
.
This approach works because if you're on a slope (i.e., nums[mid] < nums[mid + 1]
), a peak must exist in that direction. If you're on a "downhill" or "plateau", a peak could be at mid
or in the other direction.
Consider the input nums = [1, 2, 1, 3, 5, 6, 4]
.
left = 0
, right = 6
, mid = 3
(nums[3]=3
).nums[3]=3
and nums[4]=5
. Since 3 < 5
, move left
to mid + 1 = 4
.left = 4
, right = 6
, mid = 5
(nums[5]=6
).nums[5]=6
and nums[6]=4
. Since 6 > 4
, move right
to mid = 5
.left = 4
, right = 5
, mid = 4
(nums[4]=5
).nums[4]=5
and nums[5]=6
. Since 5 < 6
, move left
to mid + 1 = 5
.left = right = 5
. Return 5
as the index of a peak element (nums[5]=6
).The process finds a peak efficiently, without checking every element.
nums
, because we may need to check each element. Space is O(1).
The binary search is possible because, regardless of the array's order, there is always a peak in any subarray, and the search always moves toward one.
The "Find Peak Element" problem can be solved efficiently by leveraging a binary search approach. By always moving towards a neighbor that is larger, we guarantee finding a peak in logarithmic time. The key insight is that, due to the definition of a peak and the boundary conditions, a peak always exists, and we do not need to check every element. This makes the solution both elegant and highly efficient.