题目
给你一个整数数组 nums
,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
输入: nums = [1,2,3,1] 输出: 2 解释: 3 是峰值元素,你的函数应该返回其索引 2。
题解
第一种
首先定义了一个常量minv,它表示负无穷,用来表示数组边界情况。然后获取了数组的长度n和左右指针l和r的初始值,l为0,r为n-1,然后进入while循环,循环的条件是左指针小于右指针。在循环中,首先计算出中间值m,采用位运算符的方式避免了使用除法操作,然后分别计算出中间值左右两侧的值lv和rv。由于边界情况的存在,需要判断m是否在数组的边界内,如果在边界外则使用minv表示,接着判断中间值m是否为峰值元素,即q[m]是否大于其左右两侧的值lv和rv。如果是,则直接返回m作为峰值元素的下标,如果不是,则需要判断m左侧或右侧的元素是可能成为峰值元素。如果q[m]小于lv,则峰值元素一定在左侧,将右指针r更新为m-1;如果q[m]小于rv,则峰值元素一定在右侧,将左指针l更新为m+1,最后如果循环结束还没有找到峰值元素,则返回左指针l作为峰值元素的下标
var findPeakElement = function (q) { const minv = -Infinity; const n = q.length; let l = 0; let r = n - 1; while (l < r) { const m = l + r >> 1; const lv = m > 0 ? q[m - 1] : minv; const rv = m + 1 < n ? q[m + 1] : minv; if (q[m] > lv && q[m] > rv) return m; if (q[m] < lv) r = m - 1; else l = m + 1; } return l; };
第二种
我们先初始化左右指针,左指针指向数组的第一个元素,右指针指向数组的最后一个元素,然后进入循环,当左指针小于右指针时,去计算中间位置的索引值mid,采用向下取整的方式,如果中间位置的元素大于其相邻元素(即mid位置的元素大于mid+1位置的元素),则峰值元素可能在mid位置的左侧或mid位置本身,将右指针指向mid位置,否则,峰值元素可能在mid位置的右侧,将左指针指向mid位置的右侧,循环结束后,返回右指针的值,即为峰值元素的索引
var findPeakElement = function(nums) { let l = 0, r = nums.length - 1, mid; while(l < r){ mid = Math.floor((l + r) / 2); if(nums[mid] > nums[mid + 1]){ r = mid; }else{ l = mid + 1; } } return r };