162. 寻找峰值

题目

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

给定一个输入数组 nums其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。

数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞

示例 1:

输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2
示例 2:

输入: nums = [1,2,1,3,5,6,4]
输出:15
解释: 你的函数可以返回索引 1,其峰值元素为 2
或者返回索引 5, 其峰值元素为 6
说明:

你的解法应该是 O(logN) 时间复杂度的。

在真实的面试中遇到过这道题?

思路

注意,这里要求解法的复杂度为:O(logN) ,我们第一直接想到的是二分查找,但是这里的数组元素不是有序的,如果使用二分查找,就不能依据有序性来决定跳转策略,所以这里需要我们分析数组的特点,来制定二分查找的跳转策略,可以根据反证法进行证明这种跳转策略的合理性
关键点:改造传统的二分查找过程,不是根据数组的有序性而是根据数组和题目的特点来决定跳转策略

代码

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        
        int n = nums.size();
        if(n == 0)
            return -1;
        int l = 0;
        int r = n-1;
        //在给定范围内寻找一定存在的满足条件的值,左右端点也是查找的对象
        //所以这里的循环条件使用<=
        wrile(l <= r)
        {   //4->1或者2,
            //3->1
            //直白的写出来,使跳转更容易理解,程序也更加的直白
            //不要使用过于隐晦的技巧
            if(r-l == 0)
                return l;
            if(r-l == 1)
                return (nums[l] > nums[r])?l:r;
            int mid = l+(r-l)/2;
            //这里的查找方向跳转可以使用反证法证明
            if(nums[mid-1] > nums[mid])
                r = mid-1;//往更高的点的方向转进
            else if(nums[mid+1] > nums[mid])
                l = mid+1;//往更高的点的方向转进
            else
                return mid;
        }
        return -1;      
    }
};

posted on 2021-05-01 14:28  朴素贝叶斯  阅读(66)  评论(0编辑  收藏  举报

导航