每天一道LeetCode-----在给定序列中找到满足nums[i]>nums[i-1]&&nums[i]>nums[i+1]的位置,要求时间复杂度是O(logN)

Find Peak Element

原题链接Find Peak Element

给定一个序列,找到一个位置i满足 nums[i]>nums[i1]&&nums[i]>nums[i+1] ,其中 nums[1] nums[n] 可以看成负无穷。要求时间复杂度是O(logN)

本题实际上是局部最大值的问题,如果从头遍历到尾寻找第一个满足条件的位置i,那么一定有下面两个条件

  • nums[0 : i]是递增的
  • nums[i+1]<nums[i]

所以如果是顺序遍历的话只需要找到第一个满足条件二的位置即可,因为满足条件二就间接使得条件一成立

代码如下,复杂度为O(N)

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        for(int i = 1; i < nums.size(); ++i)
        {
            if(nums[i] < nums[i - 1])
                return i - 1;
        }
        return nums.size() - 1;
    }
};

O(logN)的解法肯定和二分有关,考虑 nums[middle] ,本题不能拿它和 nums[left] 以及 nums[right] 比较,因为约束条件是大于相邻元素,所以把目光放在 nums[middle+1] 上,如果 nums[middle]>nums[middle+1] ,那么右侧满足,可以将范围缩小到 [left:middle] 上,同理如果小于可以将范围缩小到 [middle+1:right]

可以这样缩小范围的原因是nums[0]和nums[n-1]已经满足一侧的条件,即nums[0]>nums[-1],nums[n-1]>nums[n],所以如果左边缩小到nums[0],那么0就是目标位置,同理右边n-1是目标位置

代码如下

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        while(left < right)
        {
            int middle = left + (right - left) / 2;
            if(nums[middle] > nums[middle + 1])
                right = middle;
            else
                left = middle + 1;
        }
        return left;
    }
};

本题主要是弄清楚二分法不一定必须拿nums[middle]和nums[left]和nums[right]比较,当约束条件是相邻元素时,可以和左右两边进行比较。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值