峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

题解
标签:二分查找
定理:如果i<n−1且nums[i]<nums[i+1],那么在下标[i+1,n−1]中一定存在至少一个峰值。
证明:反证法,假设下标[i+1,n−1]中没有峰值。
由于i+1不是峰值且nums[i]<nums[i+1],所以一定有nums[i+1]<nums[i+2]成立,否则i+1就是峰值了。注意题目保证相邻元素不同,不存在相邻元素相等的情况。
由于i+2不是峰值且nums[i+1]<nums[i+2],所以一定有nums[i+2]<nums[i+3]成立,否则i+2就是峰值了。
依此类推,得
nums[i]<nums[i+1]<nums[i+2]<⋯<nums[n−1]>nums[n]=−∞
这意味着nums[n−1]是峰值,矛盾,所以原命题成立。
同理可得,如果i<n−1且nums[i]>nums[i+1],那么在[0,i]中一定存在至少一个峰值。
所以,通过比较nums[i]和nums[i+1]的大小关系,从而不断地缩小峰值所在位置的范围,二分找到峰值。
/*
定理:如果i<n−1且nums[i]<nums[i+1],那么在下标[i+1,n−1]中一定存在至少一个峰值。
同理可得,如果i<n−1且nums[i]>nums[i+1],那么在[0,i]中一定存在至少一个峰值。
所以,通过比较nums[i]和nums[i+1]的大小关系,从而不断地缩小峰值所在位置的范围,二分找到峰值。
*/
class Solution {
public int findPeakElement(int[] nums) {
int left=0,right=nums.length-1;
while(left<right){
int mid=(left+right)/2;
if(nums[mid]<nums[mid+1]) left=mid+1;
else right=mid;
}
return left;
}
}

450

被折叠的 条评论
为什么被折叠?



