Description
A peak element is an element that is strictly greater than its neighbors.
Given an 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] = -∞.
You must write an algorithm that runs in O(log n) time.
Examples
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.
思路
这道题说是要找到“PeakIndex”,也就是峰值数字的序号
那他本质上就是一个找极大值的问题
因为题目限定了==O(log n)==的时间复杂度,所以这必然是一个用二分法查找的问题
我一开始想的比较复杂,觉得需要比较每个subList的头和尾,当数值发生降落的时候,则这段subList中必然存在peak;当这种情况不出现,就在两边分别寻找最大值,然后比较哪个更大,就用哪个,这个想法对应了代码1
但其实不用这样!
因为只要找极大值(而非最大值),那么当我们用middle分割了中部就能知道
- 如果nums[middle] < nums[middle + 1],那么右侧必然出现极大值(并不意味着左边不出现!但题目要求只用找到一个即可)
- 如果nums[middle] > nums[middle + 1],那么左侧必然出现极大值(至少nums[middle]的右侧已经比他小了)
根据这一点,就可以写出很simple的代码,对应于代码2
代码
class Solution {
int max = Integer.MIN_VALUE;
public int PeakIndex(int[] nums, int start, int end){
if(start == end || start == end - 1){
int max_ = Math.max(nums[start], nums[end]);
if (max_ < max)
return -1;
max = max_;
if(nums[start] > nums[end])
return start;
else
return end;
}
int mid = (start + end) / 2;
if(nums[start] > nums[mid])
return PeakIndex(nums, start, mid);
if(nums[mid] < nums[mid + 1] && nums[mid + 1] > nums[end])
return PeakIndex(nums, mid + 1, end);
int left = PeakIndex(nums, start, mid);
int right = PeakIndex(nums, mid + 1, end);
if(right == -1)
return left;
else
return right;
}
public int findPeakElement(int[] nums) {
return PeakIndex(nums, 0, nums.length - 1);
}
}
class Solution {
public int PeakIndex(int[] nums, int start, int end){
if(start == end || start == end - 1){
if(nums[start] > nums[end])
return start;
else
return end;
}
int mid = (start + end) / 2;
if(nums[mid] > nums[mid + 1])
return PeakIndex(nums, start, mid);
else
return PeakIndex(nums, mid + 1, end);
}
public int findPeakElement(int[] nums) {
return PeakIndex(nums, 0, nums.length - 1);
}
}