LeetCode热题(JS版) - 162. 寻找峰值

90 阅读1分钟

问题描述

给你一个长度为 n 的整数数组 nums,其中 nums[i] ≠ nums[i + 1],请你找到峰值元素并返回其索引。

定义:峰值元素是指其值大于左右相邻值的元素。

数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞

示例

输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,因为它大于 21

解法

我们可以使用二分查找来解决该问题。具体步骤如下:

  • 首先,如果我们把整个数组画出来,可以发现,只要存在峰值元素,在二分查找时必然会遇到一个峰值元素。

  • 假设中间元素为 mid,它与相邻元素 mid - 1mid + 1 进行比较。如果满足 nums[mid] > nums[mid + 1],则说明左侧的元素 mid - 1 可能也是峰值元素(因为 nums[mid] 比相邻右侧的元素大,但不能排除 nums[mid - 1]nums[mid - 2] 大的情况),或者当前位置就是峰值元素。根据这一点,我们将搜索区间缩小为 [left, mid]

  • 反之,如果满足 nums[mid] <= nums[mid + 1],则说明右侧的元素 mid + 1 更可能是峰值元素(因为 nums[mid + 1]nums[mid] 大)。在这种情况下,将搜索区间缩小为 [mid + 1, right]

如此迭代下去,最终一定能够找到一个峰值元素。

代码实现

以下是使用 Typescript 实现的代码:

function findPeakElement(nums: number[]): number {
  let left = 0;
  let right = nums.length - 1;

  while (left < right) {
    const mid = Math.floor((left + right) / 2);
    if (nums[mid] > nums[mid + 1]) {
      // 峰值只能在左侧或者当前位置
      right = mid;
    } else {
      // 峰值只能在右侧
      left = mid + 1;
    }
  }

  return left;
}

image.png

时间复杂度分析

由于每次可以将搜索区间减少一半,因此时间复杂度为 O(logn)O(\log n)。而空间复杂度则为常数级别,即 O(1)O(1)

因此,算法的时间复杂度为 O(logn)O(\log n),空间复杂度为 O(1)O(1)