JS算法-寻找峰值

317 阅读2分钟

题目

给你一个整数数组 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
};

坚持努力,无惧未来!