162 寻找峰值
峰值元素是指其值大于左右相邻值的元素。
给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。
数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞。
示例 1:
输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,
示例 2:
输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5
解释: 你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5,
说明:
你的解法应该是 O(logN) 时间复杂度的。
这题注意是 中等难度的,做之前感觉有点不合理,以为应该是 easy,做之后,发现确实应该是 medium ,看博客基本都说二分,感觉都没说到重点?为什么能用二分?
首先注意复杂度要求,会想到二分,然后又想到数组是无序的,不适合用二分,但是除了二分也不可能满足该复杂度要求了。所以确定用二分。
然后,这题考的是数学。
两端是最低点,所以这题一定有解,而且题目要求任意解即可,因此可以用二分。
这题只要理解了这一点,就能做出来核心思想:取mid值,只要nums[mid-1] 大于nums[mid] ,则mid左边一定有峰值 反之,mid-1右边一定存在峰值,因为两端无穷小,明白不了的画张图理解一下
然后,看代码注释
var findPeakElement = function(nums) {
if(nums.length==1){
return 0;
}
var l=0;
var r=nums.length-1;
//这里需要注意一下 js的 / 号不是整除
var mid=Math.floor((l+r)/2);
while(l<=r){
//最后的结果必然是 l,r相邻,此时取两者之间大的一定是峰值
if(mid==l){
return nums[l]>nums[r]?l:r;
}
else if(nums[mid-1]>nums[mid]){
r=mid;
}
else{
l=mid;
}
mid=Math.floor((l+r)/2);
}
};