162. 寻找峰值 Medium
峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞
。
你必须实现时间复杂度为 O(log n)
的算法来解决此问题。
示例 1:
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入:nums = [1,2,1,3,5,6,4]
输出:1 或 5
解释:你的函数可以返回索引 1,其峰值元素为 2;或者返回索引 5, 其峰值元素为 6。
解题思路
输入: 一个数组 nums
输出: 返回任意一个峰值所在位置
本题属于二分查找峰值问题。
我们可以用二分查找快速定位峰值的位置,每次 mid
都和下一个值比较
假如比下一个值大,则说明峰值可能是当前位置或者在当前位置的左侧,将搜索区间缩小到 [left, mid]
假如比下一个值小,则说明峰值一定在当前位置的右侧,我们将区间缩小到 [mid + 1, right]
最终我们一定会得到 left = right = 峰值
的情况,返回 left
或者 right
都可以
代码实现
python
from typing import List
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
# 初始化左右指针
left, right = 0, len(nums) - 1
# 二分查找
while left < right:
mid = (left + right) // 2 # 取中间位置
# 判断 mid 处的元素是否比右边元素大
if nums[mid] > nums[mid + 1]:
# 如果是,说明峰值在左边(包括 mid)
right = mid
else:
# 否则峰值一定在右边
left = mid + 1
# 最终 left == right,即为峰值索引
return left
javascript
/**
* @param {number[]} nums
* @return {number}
*/
var findPeakElement = function(nums) {
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;
};
复杂度分析
时间复杂度:O(log n)
空间复杂度:O(1)