从何时你也忌讳空山无人,从何时开始|

Drunker•L

园龄:4个月粉丝:0关注:0

162. 寻找峰值

寻找峰值
峰值元素是指其值严格大于左右相邻值的元素。

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

思路

要在时间复杂度为 O(log⁡n)O(logn) 的条件下解决这个问题,我们可以使用二分查找算法。考虑到数组可能包含多个峰值,但只需要返回其中任何一个峰值的索引,可以通过二分查找来优化搜索过程。

题目分析:

  • 峰值元素是指其值严格大于左右相邻值的元素。
  • 如果我们发现 nums[mid] > nums[mid + 1],那么峰值一定在 mid 左边(包括 mid)。
  • 如果我们发现 nums[mid] < nums[mid + 1],那么峰值一定在 mid 右边。

通过这种方式,二分查找能够将搜索空间缩小一半,因此时间复杂度为 O(log⁡n)O(logn)。

class Solution {
    public int findPeakElement(int[] nums) {
        int n = nums.length;
        int left = 0, right = n - 1;
        while(left < right){
            int mid = left + (right - left) / 2;
            if(nums[mid] > nums[mid + 1]) {
                right = mid;
            }else{
                left = mid + 1;
            }
        }
        return left;
    }
}

解释一下:

局部最大趋势

  • 如果 nums[mid] < nums[mid + 1],说明 nums[mid + 1]nums[mid] 大,意味着当前 mid 位置还不是一个峰值,且峰值应该位于右边。这是因为峰值是局部最大的元素,如果右边的元素更大,那么峰值必然在右侧。所以我们可以把 left 移动到 mid + 1,从而缩小搜索区间,继续在右半部分查找峰值。
  • 如果 nums[mid] > nums[mid + 1],说明 nums[mid] 可能是一个局部峰值,因为左边的元素比右边的元素大。在这种情况下,峰值可能就在 mid 或者它的左侧,因此我们将 right 设置为 mid,继续在左半部分查找。

这里有个点注意:如果第一种情况, mid 位置不是峰值,自然下一次就不将其纳入我们需要搜索的范围之中去,所以我们写 left = mid + 1;如果是第二种情况, mid 处可能是峰值,意味着下一次我们还是要将其纳入到我们搜索的范围当中去,所以我们写right = mid。二分法工作的区间是[left,right]的一个闭区间。

本文作者:Drunker•L

本文链接:https://www.cnblogs.com/drunkerl/p/18646225

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Drunker•L  阅读(26)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起