- Are there multiple peaks? And which one should we return?
- What is the value of
nums[-1]andnums[n]? (n is the size ofnums)
Input: nums = [1,2,3,1]
Output: 2
- Size is
1.
Input: [1]
Output: 0
- Peak is at the beginning or the end.
Input: [1,2,3] or [3,2,1]
Output: 2 or 0
- Multiple peaks.
Input: [1,2,1,3,1]
Output: 1 or 3
Idea!! We always walk toward the higher position, then we will arrive at the peak eventually. (人往高處爬,水往低處流) We can apply this idea with binary search. There are several cases when choosing the middle:
- The
middleis the peak: We just return the current index.
M
/ \
/ \- The peak is at the left part: Then we go to the left part.
Peak
/ \
/ \
M
\ - The peak is at the right part: Then we go to the right part.
Peak
/ \
/ \
M
/- The
middleis the lowest point: Then it's fine to go either left or right, because we will eventually arrive at the peak.
\ /
\ /
M fun findPeakElement(nums: IntArray): Int {
// Edge case: size == 1, then it's the peak
if (nums.size <= 1) return 0
val n = nums.size
// Two corner cases: the first and the last element is the peek
if (nums[0] > nums[1]) return 0
if (nums[n - 2] < nums[n - 1]) return n - 1
// Then we search the rest range of array
var left = 1
var right = n - 2
while (left <= right) {
val middle = left + (right - left) / 2
// Case 1. Peak is at middle
if (nums[middle - 1] < nums[middle] && nums[middle] > nums[middle + 1]) return middle
// Case 2. Peak is at right part
else if (nums[middle] < nums[middle + 1]) left = middle + 1
// Case 3. Peak is at left part
else if (nums[middle - 1] > nums[middle]) right = middle - 1
}
// Dummy return
return -1
}