描述

给定一个长度为n的数组nums,请你找到峰值并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个所在位置即可。
1.峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于
2.假设 nums[-1] = nums[n] = -\infty
3.对于所有有效的 i 都有 nums[i] != nums[i + 1]
4.你可以使用O(logN)的时间复杂度实现此问题吗?

数据范围:
1 \le nums.length \le 2\times 10^5 \1nums.length2×105 
-2^{31}<= nums[i] <= 2^{31} - 1231<=nums[i]<=2311

如输入[2,4,1,2,7,8,4]时,会形成两个山峰,一个是索引为1,峰值为4的山峰,另一个是索引为5,峰值为8的山峰,如下图所示:

示例1

输入:
[2,4,1,2,7,8,4]
复制
返回值:
1
复制
说明:
4和8都是峰值元素,返回4的索引1或者8的索引5都可以     

示例2

输入:
[1,2,3,1]
复制
返回值:
2
复制
说明:
3 是峰值元素,返回其索引 2   
解题思路:
本题用暴力解法也能解
用二分的话需要观察其中的规律,因为题目假设了nums[-1] = nums[n] = -\infty−∞,因此使用二分法有上升趋势的一边一定存在峰值,且峰值为right

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @return int整型
     */
    /*int findPeakElement(vector<int>& nums) {
        // write code here
        int n = nums.size();
        if (n == 1) return 0;
        if (n == 2) {
            if (nums[0] > nums[1]) {
                return 0;
            } else {
                return 1;
            }
        }
        if (nums[0] > nums[1]) {
            return 0;
        }
        int left = 0;
        int right = n - 1;
        for (int i = 1; i < n-1; i++) {
            if (nums[i] > nums[i-1] && nums[i] > nums[i+1]) {
                return i;
            }
        }
        if (nums[n-1] > nums[n-2]) {
            return n-1;
        }
        return -1;
    }*/
    int findPeakElement(vector<int>& nums) {
        int n = nums.size();
        int left = 0;
        int right = n - 1;
        while(left < right) {
            int mid = (right-left)/2 + left;
            //cout <<mid << endl;
            if (nums[mid] > nums[mid-1] && nums[mid] > nums[mid+1]) {
                return mid;
            }
            if (nums[mid] > nums[mid+1]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
         
        return right;
    }
};