寻找峰值元素

问题描述

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

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log n) 的算法来解决此问题。
对于所有有效的 i 都有 nums[i] != nums[i + 1]。
原题

思路与方法

对于此题很容易想到的方法是遍历数组,查看每一个元素是否为峰值,但时间复杂度是O(n),而题目要求O(logn),因为该题有任意相邻元素不相等并且nums[-1] = nums[n] = -∞ 这两个条件,可知一定存在峰值,并且对于任意一个元素,若相邻元素大于它则在大于它的元素方向上必然有峰值。以右边为例,若对于元素num[i]有num[i+1]>num[i],假设num[i]的右边没有峰值,则num[i+1]不为峰值,所以num[i+1]<num[i+2],num[i+2]也不为峰值,所以num[i+2]<num[i+3],以此类推直到num[n-2]<num[n-1],而num[n-1]是末尾元素,又有nums[n] = -∞,故num[n-1]>num[n]并且num[n-1]>num[n-2],即num[n-1]为峰值,与假设矛盾,故该方向上一定有峰值。利用此点可以用二分法降低时间复杂度,每次取区间中点,若为峰值直接返回,若左侧元素大则将区间缩至左半区间,继续二分,若右侧元素大则将区间缩至右半区间,循环此过程直到找到峰值。

Code

public int findPeakElement(int[] nums) {
           int left=0,right=nums.length-1;
           //int ans=0;
           while(left<right){
                int mid=(left+right)/2;
                int before=mid>0?nums[mid-1]:Integer.MIN_VALUE;//左侧元素
                int after=mid<nums.length-1?nums[mid+1]:Integer.MIN_VALUE;//右侧元素
                if(nums[mid]>=before&&nums[mid]>=after){
                    return mid;
                }else if(nums[mid]<before){
                    right=mid-1;
                }
                else if(nums[mid]<after){
                    left=mid+1;
                }
           }
           return left;
    }

复杂度分析

二分法时间复杂度是O(logn),内存上只用了常数量级的空间,故空间复杂度为O(1)

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值