Skip to content

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)

链接

162 国际版

162 中文版