问题描述
给你一个长度为 n 的整数数组 nums,其中 nums[i] ≠ nums[i + 1],请你找到峰值元素并返回其索引。
定义:峰值元素是指其值大于左右相邻值的元素。
数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞。
示例
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,因为它大于 2 和 1。
解法
我们可以使用二分查找来解决该问题。具体步骤如下:
-
首先,如果我们把整个数组画出来,可以发现,只要存在峰值元素,在二分查找时必然会遇到一个峰值元素。
-
假设中间元素为
mid,它与相邻元素mid - 1和mid + 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;
}
时间复杂度分析
由于每次可以将搜索区间减少一半,因此时间复杂度为 。而空间复杂度则为常数级别,即 。
因此,算法的时间复杂度为 ,空间复杂度为 。